A follow-up story for PR https://github.com/strongloop/loopback-next/pull/2576
Add new authentication strategies in loopback4-example-shopping to investigate how to verify a 3rd-party user using oauth2, and track the user using session.
The acceptance criteria is written with oauth2+google, the story owner can choose any 3rd party auth provider: oauth2+fb, oauth2+google, etc...
[x] ~Create an oauth2 strategy to authenticate the users by interacting with 3rd-party provider's auth server~ completed with https://github.com/strongloop/loopback-next/pull/4919
login/facebook and login/facebook/callback. And this is the most important user experience we need to figure out from design's perspective.[x] Track the user profile using session. Keep the session related functionalities as simple as possible, we can create sub-stories to enhance.
docs/strategies/oauth2.md~After talking with @raymondfeng yesterday, he suggested we investigate the two main flows of OAuth
Implicit Flow is when all of the logic for authentication is in the UI flow, and the goal is to get the access token, and then pass this token to the backend when accessing endpoints.
https://auth0.com/docs/flows/concepts/implicit
Authorization Code Flow is when the backend server has to direct the user to login, and the oauth server sends an authorization code to the backend. The backend uses this temporary code to get an access token and passes it to the client. The client then has to use it to access all the backend's protected endpoints. The backend, when sent a token, needs to always double-check with Facebook that this token is a valid token...so it needs to call the FB api to do this.
https://auth0.com/docs/flows/concepts/auth-code
With regards to https://www.npmjs.com/package/@loopback/authentication-passport , we know the adapter works well with passport-jwt and passport-http.
We need to adjust the design (if necessary) to ensure that it can work well with OAuth2.0 passport-* modules like passport-facebook, passport-google, etc.
Most people uses Facebook authentication to get a token to then invoke Facebook API.
This is not our goal per se.
We want to use it to get a Bearer token to protect our server API.
We should also look into passport-http-bearer as well : http://www.passportjs.org/docs/oauth2-api/
I began playing around with Facebook stuff in my investigation.
All of these projects need an App ID and secret of a Facebook app that is registered via the Facebook Developer Console.
https://github.com/emonddr/express-4.x-facebook-example
server.js is an example from the author of passport-facebook.
blogger_example.js is an example from a blogger that was playing with passport-facebook.
https://github.com/emonddr/authapp
It uses https://www.npmjs.com/package/@loopback/authentication-passport adapter to wrap passport-http module. It uses the Provider approach.
https://github.com/emonddr/authapp_fb
It uses https://www.npmjs.com/package/@loopback/authentication-passport adapter to wrap passport-facebook module. It uses the Provider approach.
It is incomplete. I need to get more familiar with the redirecting url flows that seem to occur with OAuth2.0.
Currently my app suffers from this error
Unhandled error in GET /auth/facebook/callback: 500 InternalServerError: TypeError: self.redirect is not a function
at Strategy.strategy.error (/Users/dremond/Documents/all_facebook_auth_examples/authapp_fb/node_modules/@loopback/authentication-passport/src/strategy-adapter.ts:57:16)
at Strategy.OAuth2Strategy.authenticate (/Users/dremond/Documents/all_facebook_auth_examples/authapp_fb/node_modules/passport-oauth2/lib/strategy.js:285:21)
at Strategy.authenticate (/Users/dremond/Documents/all_facebook_auth_examples/authapp_fb/node_modules/passport-facebook/lib/strategy.js:84:41)
at Promise (/Users/dremond/Documents/all_facebook_auth_examples/authapp_fb/node_modules/@loopback/authentication-passport/src/strategy-adapter.ts:61:16)
at new Promise (<anonymous>)
at StrategyAdapter.authenticate (/Users/dremond/Documents/all_facebook_auth_examples/authapp_fb/node_modules/@loopback/authentication-passport/src/strategy-adapter.ts:35:12)
at AuthenticateActionProvider.action (/Users/dremond/Documents/all_facebook_auth_examples/authapp_fb/node_modules/@loopback/authentication/src/providers/auth-action.provider.ts:52:40)
at process._tickCallback (internal/process/next_tick.js:68:7)
In https://github.com/emonddr/authapp_fb/blob/master/src/controllers/facebook.controller.ts
I was trying to have the authentication strategy handle
and ran into the self.redirect error above.
These endpoints are decorated like this:
In pure custom authentication strategies, there is a way to get the options for every requested url that is decorated with @authenticate : https://loopback.io/doc/en/lb4/Loopback-component-authentication.html#update-custom-authentication-strategy-to-handle-options .
Currently there is no way to pass these into the strategy adapter
https://www.npmjs.com/package/@loopback/authentication-passport .
we need to be able to pass in options in the line
strategy.authenticate(request);
A good place to pass in the request options is probably as an optional parameter in the constructor. https://github.com/strongloop/loopback-next/blob/labs/passport-adapter/labs/authentication-passport/src/strategy-adapter.ts#L25
Since an authentication provider strategy is instantiated with each request url, the authentication strategy should obtain the options from the metadata of the endpoint decorated with @authenticate, and pass in the options in the constructor of the strategy adapter as another optional parameter.
In my facebook authentication strategy provider, on this line
https://github.com/emonddr/authapp_fb/blob/master/src/provider/passportfacebook.provider.ts#L52
instead of
return new StrategyAdapter(facebook, AUTH_STRATEGY_NAME);
we would need to do
return new StrategyAdapter(facebook, AUTH_STRATEGY_NAME, request_options);
where request_options are the options specified in the @authenticate decorator for that request (specific endpoint).
Also part of authapp_fb (but not interacting with the Loopback 4 server at all) was an
example given by Facebook itself.
I just piggy-backed it as a static HTML website on the Loopback4 server.
The code is here:
https://github.com/emonddr/authapp_fb/blob/master/public/facebook/login.html
The /facebooklogin endpoint is defined here : https://github.com/emonddr/authapp_fb/blob/master/src/application.ts#L25
Thanks for sharing @emonddr . I am running into the exact same problem with Loopback4 when trying to implement facebook authentication.
I know RestServer and RestApplication offer API's for redirect. Should we be leveraging this somehow in the Strategy?
Unhandled error in GET /auth/facebook: 500 InternalServerError: TypeError: self.redirect is not a function
at Strategy.strategy.error (c:\Users\sbesong\Documents\WORKSPACE\VOID\myworry-server\node_modules\@loopback\authentication-passport\src\strategy-adapter.ts:73:16)
at Strategy.OAuth2Strategy.authenticate (c:\Users\sbesong\Documents\WORKSPACE\VOID\myworry-server\node_modules\passport-oauth2\lib\strategy.js:285:21)
at Strategy.authenticate (c:\Users\sbesong\Documents\WORKSPACE\VOID\myworry-server\node_modules\passport-facebook\lib\strategy.js:84:41)
at Promise (c:\Users\sbesong\Documents\WORKSPACE\VOID\myworry-server\node_modules\@loopback\authentication-passport\src\strategy-adapter.ts:77:16)
at new Promise (<anonymous>)
at StrategyAdapter.authenticate (c:\Users\sbesong\Documents\WORKSPACE\VOID\myworry-server\node_modules\@loopback\authentication-passport\src\strategy-adapter.ts:47:12)
at AuthenticateActionProvider.action (c:\Users\sbesong\Documents\WORKSPACE\VOID\myworry-server\node_modules\@loopback\authentication\src\providers\auth-action.provider.ts:52:40)
at process._tickCallback (internal/process/next_tick.js:68:7)
Is there any update on this?
I also have the same concern with passport-github.
I found this deposit which seems to correct the problem:
https://github.com/sourcefuse/loopback4-authentication
Thanks for investigating that issue @emonddr. I was working on a strategy for keycloak and end up with the same problem.
Unhandled error in GET /whoami: 500 InternalServerError: TypeError: self.redirect is not a function
at Strategy.strategy.error (/Users/pilare/Workspace/loopback/lb-4-getting-started/node_modules/@loopback/authentication-passport/src/strategy-adapter.ts:73:16)
@jannyHou any chances for some development or instructions on how to get past that?
I tried some other approaches like:
https://github.com/codejamninja/lb4-authorization
but they are not using @loopback/authentication, which I would like to be compliant with, and had some other issues with those.
@pilare sorry for the late reply, looking, will get back to asap today.
@deepakrkris (Thank you!) is working a fix in https://github.com/strongloop/loopback-next/issues/4902, I think it's the same issue.
PR submitted for review https://github.com/strongloop/loopback-next/pull/4919
@deepakrkris, with PR #4919 landed, anything we need to do for this task? Thanks.
@dhmlau the PR https://github.com/strongloop/loopback-next/pull/4899 will complete the pending items in this task.
following pending items in this issue will be completed by https://github.com/strongloop/loopback-next/pull/4899
Most helpful comment
following pending items in this issue will be completed by https://github.com/strongloop/loopback-next/pull/4899