External authentication providers and authenticating requests to RESTful API - node.js

I'm working on adding google login to my web app. It's a RESTful app, so once a user is logged in, each individual request must be authenticated with a token.
Currently, I create my own tokens using JWT. I can add useful information to the token object to help with state management.
My question is: once I add google as an authentication provider, do I then need send every request to Google to be authenticated, rather than authenticating it on my own server? Do I then lose the ability to customize the content of the token?
With external authentication providers, is it normal to manage separate JWTs for calls to your RESTful API?

Normally, you'll have the login action use the third party to identify the user. Your internal code will probably create/store/fetch an app local user profile of some sort, and you'll create your JWT based on that. Further calls to your API bearing a valid token are then trusted to have already been authenticated and therefore need no further calls to the auth provider.

Related

Link another account with oauth on passport

Context:
1 spa
1 api
1 existing passport strategy with jwt
Feature:
Connect additional account with oauth to the existing account
I already have an authentification using passport on nodejs.
This generates a jwt allowing the users to authenticate them with a bearer token in the header of each request to the api.
I would like to add an additional oauth connection to the existing account (actually it is docusign but I think the problem could be the same with other connections).
When there is the redirection with the authorization code, I cannot identify the user which has initiated the connection because I don't have the bearer token in the request header anymore and the data between the two accounts can be different (different emails for example).
Is there a workaround for this or did I miss something?
Thank you for your help
Passport has an Authorize method which can be used to authenticate with a secondary IdP. For example:
Use Passport#Login to enable the user to login to your application's primary IdP
Use Passport#Authorize to enable the user to authenticate with a secondary IdP (such as DocuSign) as needed.
Regarding state for your redirect method (determining which IdP should be used to exchange the authorization code for an access token):
You can use the state parameter that is sent as part of the OAuth authorization code grant flow. But be sure to also use the parameter as a random nonce to guard against a CSRF attack. Eg, send idp1|random_nonce so you can both check the nonce and know that you should communicate with idp1, not idp2.
You can use your application's session machinery to maintain your app's state knowledge of which IdP you're working with at the time.
The only one I can think of is having 2 apps. Each can run on a different port or vd. Each would have their own passport strategy. The two apps can redirect to eachother and/or communicate using API endpoints to pass data between them.

Should I make 3rd party API calls in backend or frontend?

I have an API and that API needs some data from the Microsft Graph API. I was thinking of implementing an endpoint in my API to refresh the token and use that token to make calls from the frontend. I don't know if that's optimal or safe, hence my question.
EDIT 1: To give a better perspective of what I have, this is the logic I have at the moment. Tell me if this is correct please.
User requests my API's authorization endpoint, which has the Azure's secret key, then the user is redirected to the Microsft oAuth login page. Once logged in oAuth, Microsoft redirects the user to my API, where it saves the JWT tokens in the user's cookies, so the user can refresh the token anytime.
In order to refresh the token, the user simply just makes a call to myapi.com/auth/microsoft/token, where it has the secret key, and it refreshes.
Generally I would recommend always making the 3rd party calls from the back end. It gives you more control and avoids any cross origin complications.
You also want to be aware of any API keys. Most APIs require a key for access and often that key is private and you wouldn't want to share on the front end.
MS Azure APIs have an application and secret token. You cannot expose the secret token to the client. To call directly from the client you would use OAuth to get a JWT token and then you can call from the SPA into the MS Web APIs with that token.
https://learn.microsoft.com/en-us/azure/active-directory/develop/authentication-scenarios#single-page-application-spa
In contrast, there are other 3rd party APIs that are designed to be called only from the front-end. Stripe for example is a payment processing API where the UI can call directly into Stripe and then the client's payment information is never actually passed to the host application, only to Stripe. This improves security.

Should my app issue it's own access tokens, when using external oauth2 provider (facebook)?

I would like to give the users a possibility to login with some external oauth2 provider (facebook) in my app. The client's part is running on mobile device in a native app.
I am not sure which of the approaches below should I prefer ?
Should the client send the user's access token by facebook with each request ? At each request backend asks facebook to validate the access token. Based on the validation's result, backend performs authorization and return corresponding result to the client.
Should the backend ask facebook to validate the access token only at user logon, then issue its own access token, return the access token back to the client and client will use this access token at making requests to the server to avoid contacting facebook at each request ?
I have read some questions about how to implement the auth with facebook and most of the devs are using B, but I haven't seen any explanation why is it good/bad to use A ?
What I see as benefits of the solutions:
backend doesn't need to care about issuing, refreshing, validating access tokens since this is done only by facebook's authorization servers.
this solution seems to be more effective, since it does not require to connect to facebook at each request.
Security tokens issued by Facebook are signed with a digital signature. The API server only needs access to the public key to validate the signature. There's no need at all to contact Facebook after the user authenticates.
A reason to issue your own tokens after the user signed in with Facebook could be to add claims to the token. But obviously having your own authorization server comes at a cost. It's up to you to weigh the pros and cons.
If you do decide to have your own authorization server, make sure not to write your own! There are open source options like Thinktecture IdentityServer.
I will vote for option B and here is my explanation,
Your API must authorise the request every time with some auth token , which cannot be external provider token, in such case anyone with an access token (eg: other developers) of other provider can access your api, basically there is no auth here.
When your sever issue access token, it's easy to validate and when needed could be revoked easily (eg: on password reset)
While authenticating , your server has fully control over issuing access token , so the validation is made only once and doesn't have to do every time while calling the API.

Authentication with React Native and API backend

I'm trying to wrap my head around oauth with a React Native app and a separate NodeJS/Express API backend. I understand https://github.com/adamjmcgrath/react-native-simple-auth offers authentication for a React Native app and http://passportjs.org/ offers authentication for a NodeJS backend. I'm unsure how to connect these two for authentication for login and access to the API.
I'd like users to login to the React Native app either by email and password or via Facebook/Twitter/Google. Once logged into the app, what do I send to the API to make sure they are authenticated and have access to a specific route?
Here is an example flow to login and see the logged-in user's settings:
User logs into React Native app via email/password or Facebook/Twitter/Google.
User is authenticated
App makes request to GET /api/settings
API verifies user is authenticated and returns that user's settings or API verifies user is not authenticated and returns a 403.
There's a whole lot to this question, so much so that it wouldn't all fit in a single SO answer, but here's some tips and a general outline that should broadly fit into what you want to accomplish.
OAuth2 Authorization
From the sounds of it, you are interested in using OAuth 2 to provide social login authorization, and would like to do first-party authentication as an alternative with an email and password. For social logins you will end up using the OAuth 2 Implicit flow to retrieve an access token, which is a widely recognized pattern. Because you are also looking to authenticate users with an email and password, you may want to familiarize yourself with OpenID Connect, which is an extension of OAuth 2 and which explicitly supports authentication in addition to authorization.
In either case, once your user has either submitted an email/password combo or granted permission through the social identity providers, you will receive in response an access token and (optionally) an ID token. The tokens, likely a JWT (JSON Web Token, see jwt.io) will come across as a base64 encoded string that you can decode to inspect the results of the JWT, which will include things like the ID of the user and other details like email address, name, etc.
For more info on the different types of flows, see this excellent overview on Digital Ocean.
Using Tokens for API Authentication
Now that you have an access token, you can pass it along with all requests to your API to demonstrate that you have properly authenticated. You'll do this by passing along the access token in your HTTP headers, specifically the Authorization header, prefacing your base64-encoded access token (what you originally received in response to your authorization request) with Bearer . So the header looks something like this:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJh...
On your API's side, you will receive that token, decode it, and then verify the ID and claims in it. Passed as part of the token in the sub property will be the subject, or ID of the user making the request. This is how you identify access and start to do things on your API side with the respective user's rights, perms, etc. It is also important that you validate the access token once you receive it on your API side, to ensure it wasn't spoofed or hand-crafted.
How it looks in RN for Implicit flows
Here's what the general process looks like in React Native for OAuth 2 Implicit flows, which is what you'll use for social identity providers:
User taps one of your social login buttons on React Native UI
Your code that responds to the buttons will build a request URL to those providers, depending on what each wants (because it differs slightly).
Using the Linking API in RN, you will open up that URL in a browser on the device which sends the user off to the social provider for them to do the login/authorization dance.
Once complete, the social provider will redirect the user to a URL you provider. On a mobile device, you will use your own custom URL scheme to move the user from the web view to your app. This scheme is something you register as part of your app, such as my-awesome-app://, and the redirect URL you pass to the social provider could look like my-awesome-app://auth_complete/. See the Linking API docs for how to configure these URL schemes and deep linking.
In the handler for that new URL scheme/deep link, you'll get the tokens passed as part of the URL. Either by hand or using a library, parse out the tokens from the URL and store them in your app. It's at this point that you can start inspecting them as JWTs, and pass them along in the HTTP headers for API access.
How it looks in RN for Resource Owner Password Grant flows
You have the option for your email/password combo for your own accounts of either sticking with the Implicit flow, or switching to the Resource Owner Password Grant flow if your API and app are trusted by each other, meaning that you are making both the app and the API. I prefer the ROPG flow on mobile apps where possible because the UX is much nicer--you don't have to open up a separate web view, you just have them type in their email and password into UI elements directly in the app. So that being said, here's what it looks like:
User taps the email/password combo login button, and RN responds with a UI that includes TextInputs for the email and password
Build a POST request to your authorization server (which may be your API, or may be a separate server) that includes the properly crafted URL and body details that passes along the email and password. Fire this request.
The auth server will respond with the associated tokens in the response body. At this point you can do the same thing previously done in step 5 above, where you store the tokens for later use in API requests and inspect them for relevant user information.
As you can see, the ROPG is more straightforward, but should only be used in highly trusted scenarios.
At the API
On the API side, you inspect for the token in the Authorization header, and as mentioned previously, and if found you assume that the user has been authenticated. It is still good security practice to valid and verify the token and user permissions. If there is no token sent with the request, or if the token sent has expired, then you reject the request.
There's certainly a ton to it, but that provides a general outline.

How to implement Oauth2 Provider in REST Api Server?

I am developing REST API Server in Node.js and it is almost Ready. Now I am trying to implement Authentication to API server. I decided to use OAuth2 for this. I think I will be Using grant type password, as most of the Apps that will use my service will be under my control.
There are some modules available https://github.com/jaredhanson/oauth2orize, I am confused on storing access token for the authorised users and mantaining sessions. As this is REST server do i need to mantain the Session, Or should i just store active tokens and related users to db and check for each request if they are valid or not?

Resources