JWT Token vs Session Token for React Native And react Js - reactjs

We are in the process of building customer app for an organisation , with technical stack
react js for portal and react-native for the mobile.
During the review, it was suggested to go for session id based user session instead of JWT Token based.
We also want to use OIDC FLow for Authentication and OAUTH2.0 for Authorization of API's
As there are suggestion for both JWT and Session ID which each of them has their own pros and cons.
Security team is insisting on the Session ID's with reasons below
JWT is Bulky , not revokable
JWTs are dangerous JWT vsSession
What should be our choice for security architecture
Do we need still Session Id to track
The Token used for the OIDC cannot be sent to UI,as it has privacy and security information
should we have to go for JWE?
Can we have hash of the token or correlation id corresponding to the OIDC TOkens and lookup on each call from client to backend , so that browser or client app need not know OIDC TOkens?
Do we really need bespoke auth service, Can API Gw itself along with any OIDC will be enough to implement end2end security without any need for writing spring base or any Authentication service
[![FLow][4]][4]

CONFIDENTIALITY
You can satisfy these concerns in a standard way via a couple of techniques, though they require a more complex flow:
Use opaque tokens that are not readable by internet clients and do not reveal any sensitive information - see The Phantom Token Pattern for how this works.
In the browser use only secure cookies (SameSite=strict, HTTP Only, AES256 encrypted), which can contain opaque tokens. See the Token Handler Pattern where there is a React SPA you can run and a Node token handler API you can plug in.
Generally these internet credentials behave like session IDs, which are also opaque, but you are using standard OAuth and your APIs still end up authorizing via digitally verifiable JWT access tokens.
TOKEN HANDLER PATTERN
For SPAs the idea is to enable a setup like this, where you plug in (and perhaps adapt) open source token handler components, rather than needing to develop them yourself. This pattern should work with any Authorization Server:
Key benefits are as follows - see these Curity resources for further details:
SPA uses only the strongest SameSite=strict cookies, with no tokens in the browser
SPA can be deployed to many global locations via a Content Delivery Network
By default, cookies are only used on Ajax requests to APIs, which gives the SPA best control over usability aspects
API FLOWS
When calling APIs the flows then work like this, and typically involve a reverse proxy placed in front of APIs, so that API code remains simple:
Web clients send a secure cookie, and a cookie decryption gets the opaque token. A second plugin then gets a JWT from the opaque token and forwards it to APIs.
Mobile clients send an opaque token to the same API paths, in which case the cookie decryption plugin does nothing. The second plugin then gets a JWT from the opaque token and forwards it to APIs.
Note that the client can still receive an expires_in field if it wants to perform optimizations to check the lifetime of access tokens, but I have always advised against this, and to instead just handle 401s reliably in clients, like this:
private async fetch(method: string, path: string): Promise<any> {
try {
// Try the API call
return await this.fetchImpl(method, path);
} catch (e) {
if (!this.isApi401Error(e)) {
throw ErrorHandler.handleFetchError(e);
}
await this.oauthClient.refresh();
try {
// Retry the API call
return await this.fetchImpl(method, path);
} catch (e) {
throw ErrorHandler.handleFetchError(e);
}
}
}

Related

Is it safe to store access token in next-auth session?

What I want is to access the customer details in the client side in next.js and I need to pass the customer access token to the backend API. Using next-auth, I was able to store the access token to the session but is it safe or is it better to use the next.js api route and use getToken function? I'm still a beginner in frontend security, I don't know if I'm just being a paranoid but I can't find a topic/post that states it is completely safe.
So by default the session strategy is set to jwt, which means your session is encoded / signed and safe to store sensitive info in.
However, NextAuth.js can be used to automatically put that accessToken you get from your OAuth provider in the JWT token via the jwt callback. Therefore you can pull it out anywhere with the getToken() method you mentioned and authenticate against Google APIs for further use (get drive contents, contacts, etc, etc, etc).
Check out this example for how to do that in the jwt callback: https://github.com/nextauthjs/next-auth-refresh-token-example/blob/57f84dbc50f30233d4ee389c7239212858ecae14/pages/api/auth/%5B...nextauth%5D.js#L67

Authorization and authentication in web application with ASP.NET Core backend and React frontend?

I have a web application, where the frontend is built with react.js and typescript and the backend is build with ASP.NET Core 3.1 and connected to a SQL Server. The SQL Server is used for saving data, which I can enter in the frontend.
Now I want to implement a custom authentication system, where I can protect different endpoints with an authorization. I know there are several ways to go for, but I don't want to use a service / library, where a user could login with his google account for example.
Jwt seems in my Opinion a good way to go here, but I really don't understand the whole system.
This article helped me already a lot: Implementing authentication and authorization with React hooks, .NET Core Web API, and SQL Server .After reading this, I don't understand the relationship between logging in and how my backend knows, that a user is logged in (for protecting my endpoints).
Of course I already read many articles about authentication and authorization for ASP.NET Core. I've read about different services like:
Auth0 (seems not a good idea, because you can login with google etc.)
IdentityUI (seems good, I've seen a few youtube tutorials but they are all using another project structure, where the frontend and backend isn't separated. So they are using the razor pages like Login.cshtml, but I don't want to render any pages in the backend, only in the frontend)
For authorization for my controller in the backend, I planned to use the following:
[Authorize] // to protect endpoint
[HttpGet]
public async Task<IEnumerable<>> GetData()
{
// some code
}
But as I already said: I don't know / understand how my backend knows if a user is logged in (and how to check it).
Could somebody provide me an appropriate tutorial or an article, where is explained, how to manage authorization and authentication for frontend and backend? Or maybe somebody knows, how to use the IdentityUI with a frontend build with react + typescript and a backend, which shouldn't render any pages.
Thanks for your attention :)
Well... for detailed flow how they work, here is RFC 6749, this is a pretty comprehensive collection of knowledge related to the topic and the easiest approach would be wiki page in general.
But to simplify the process, just get to know these things:
What is JWT
Jwt just a string that was generated by some algorithm from a public/private key pair(don't even care how it works, just give it a key pair, some lib on every language would do the rest). This JWT often contain all the information that needed to specify who the user is(big word right ? but actually, userId is enough for simple case).
It contain 3 different parts Header, Payload and Signature, and the string assured it cannot be interrupted(or just modify it as we wish, and the validation process would failed).
Further detail here.
What happen on server side?
The most basically flow was send user, password to server for validate who we are and our account exists. Then, server side would take some necessary info out of it to generate the JWT token. The server which generate JWT token was normally refer to Identity Provider.
Then that token was send back to client, and client save it somewhere for later use.
Client side use token to request other resource
Normally, Identity Provider would provide a .wellknow endpoint that contain all necessary info for other resources to gather for validation process.
Now, client side send a http request to these resources with the JWT token. They use info gathered from .wellknow endpoint to validate was the JWT valid. If it is, we are who we claim we are, authentication process success.
The end.
Over-simplyfied flow imagination in your specific case
React Client => Request login => Identity Provider => Jwt Token send back => React client save it somewhere.
React Client => Request some resource over http with the JWT token => Resource server validate it (through info from .wellknow endpoint) => Authentication success or fail => normal process => send response back to client.

Bearer Token authentication and JWT

I've been provided with a REST API which has authentication type bearer (Security Scheme Type: API Key, Header parameter name: Authorization) and which i use to authenticate the user and then fetch other data (i will only create the front end using react).
As a first step the user logs in and i sent his/her username-password to the prementioned REST API and get back an access and a refresh token.
Is anything wrong with storing these 2 tokens in a cookie in order to use them in subsequent requests? How does JWT comes into play regarding these 2 tokens? Is JWT of any use to me in this situation?
There's nothing wrong in storing the tokens in cookies, but if you're planning to have a Single Page Application with React it should be enough to store these tokens in memory. Once the user refreshes the page you can either make them sign in again or perform a silent login in the background to get a new set of tokens. In both cases the session kept on the Authorization Server should kick in and you should get new tokens without the need of user interaction.
Your tokens will be much safer if you don't keep them in cookies.
JWTs are not a requirement for access and refresh tokens. If you don't have to use them I would recommend going with opaque tokens. That said, since you do not have control over the API you might be limited to the format required by the API. If you don't want to be limited by this format you can set up your own gateway which you can use to perform token exchange or introspection and forward requests to the API with proper tokens (something which is called a Phantom Token pattern.
From my understanding of the question, you are using an identity provider which provides you with access token and refresh token for the users. That means it is a authentication as a service REST API at works here.
The REST API requires an authorisation header to be passed along with the username-password to exchange for access token and refresh token for the users. (correct me if I'm wrong) In this case, you might want to keep the authorisation header away from the users (consult the authentication as a service documentation).
You call the REST API with payloads (the user-password) along with headers like this:
Authorization: ACCESS_TOKEN
However the ACCESS_TOKEN is the one provided by the vendor for you to use the REST API. On success call of the REST API, it should return you with a set of access token and refresh token. You can then use this access token and refresh token to safe guard your own API, API that you control to provide service to your users.
The access token and refresh token might just be JWT tokens (again consult the vendor documentation).
Also if you are using an authentication as a service REST API, check the documentation if they provide a client sdk. In that case, it should show you the best practise of handling the access token and refresh token it returned.

Google OAuth2 flow and id_token refresh

I am having troubles in implementing OAuth in the right way.
I use a client/API architecture (Angular for front and Node.js for back) and I would like user to sign in using Google OAuth authentication only.
Here is what I think is the right way for the moment (tell me if I misunderstood something) :
Angular open a Google popup asking user's consent.
Once the user agree, Google Authorization server sends back to angular a verification code.
This verification code is forwarded to an API endpoint.
Then, the API asks Google Authorization server to exchange this code for an access_token, an id_token and a refresh_token.
Google sends those 3 tokens.
The API uses access_token to retrieve user from Google API
The API persists the user
Here is the little dillema, in my opinion, the access_token and refresh_token should be stored into the database and the id_token should be sent back to Angular client.
This way, it would allow the API to ask for resource in Google API and if the token expires it can still ask for a new token thanks to the refresh_token.
Client-side, the id_token is embedded in all requests thus allowing the API to identify the client and verify his authentication with Google certs from https://www.googleapis.com/oauth2/v3/certs.
Supposing this is right way to use tokens, how could I deal with id_token expiration since client does not have any refresh token ?
Thanks !
I do it slightly different (I have the same basic architecture though).
Angular decides the user needs to log in and displays a login popup.
The url in the login popup is not serviced by angular, but is instead directly run off of the backend server: /auth/google . (I use hapijs and bell, personally).
/auth/google is serviced by a bell plugin and initiates the OAUTH dance.
the end of the OAUTH dance results in my node server generating a local token (I just generate random bytes and store them in redis mapped to user ids)
because the initial login popup was created by window.open, the success page (generated on the api side rather than in angular) can use window.opener.postMessage to communicate the token back to the angular runtime.
This way, all my sensitive google credentials (the user's oauth token, refresh token if needed, and my application's api ID and secret) are only on the server, except for during the OAUTH dance relay when they're in a URL string during the client redirects. This is reasonably secure.
Then for all the actual user interactions with the api, I use the token I generated in step four to authenticate. This could be a JWT if you wanted, but I don't do it that way; I just use redis to map from 'longrandostring' -> userId. That lets me (for example) force everyone to re-login if I wipe the redis database that has all the tokens stored, or I can write a lua script to delete all the entries that map to a certain userid.
If you need a refresh token, you can set access_type=offline in the initial request to oauth2/auth, and you'll get a refresh token as part of the response, unless you've previously gotten a refresh token. You can then persist it on the server side and get new access tokens as needed. If you set approval_prompt=force as well, you'll force a new consent screen and be guaranteed a refresh token (but after some small number of refresh tokens granted to a user, older ones expire on the same application so it's best to only request them if really needed).

How to use SAML authentication in a mobile application?

I'm trying to understand how an saml authentication flow could work in a mobile environment where the client (AngularJS based), api server (Node & passport based), and idp exist on different domains.
From what I've gathered the general practice is to have the server return a 401 to the client if there's no authentication present (i.e. the client didn't include a bearer token in the request). The client understands that a 401 response indicates to open up the login endpoint on the server. When the login endpoint is opened it makes a passport call to the auth provider (which redirects the user to the auth provider's site) and supplies a callback URL. When the user authenticates, the auth provider redirects to the provided callback URL, which allows the server to retrieve information from the auth provider's response and construct a token of some sort (e.g. JWT) that can be used by the client (i.e. included in the headers) when making REST calls to identify itself.
My question is: How does the client get the token from the server? Because we're in a redirect-based authentication flow, I can't just return token from the callback function; that would just display the token in the browser without handing it off of to the client. Does the server just issue a 302 redirect pointing back to the client domain and include the authentication token in a header? Maybe I should not redirect from the client to the server in the first place and instead window.open() and use window.opener.postMessage or is that too old fashioned/mobile-unfriendly?
This question talks about authentication against a SAML IDP, but I'm interested in getting more details specifically about that last bullet point and how it would work with an AngularJS-based client.
Many examples I've seen online are either a single domain using OAuth/SAML (passport-saml-example), which avoids the issue of having the client exist on a separate domain, or use two domains with basic authentication, which avoids the issue of redirecting to some third party for authentication, but I'm having trouble finding good examples that uses all the bits and pieces I'm trying to work with.
This blog post seems very close to what I'm trying to accomplish (see googleSignInCallback) and uses a 302 redirect like I imagined but that solution relies on explicitly knowing the client URL to redirect to, which seems like it could be problematic if I wanted to support multiple client types (i.e. Native applications) in the future.
Eventually I was able to work together a solution by having my application open a browser window (Cordova's InAppBrowser) to a SAML-enabled application, have that application complete the normal SAML flow, and then that SAML-enabled application generated a JWT. My mobile application was then able to extract the JWT string from the browser window with the InAppBrowser's executeScript functionality. Then I could pass that JWT string along to my API server, which was able to validate the JWT is properly signed and trusted.
After I implemented my solution I saw that there was similar functionality available on github:
https://github.com/feedhenry-templates/saml-service
https://github.com/feedhenry-templates/saml-cloud-app
https://github.com/feedhenry-templates/saml-cordova-app
Hopefully this helps anyone else trying to deal with this issue!

Resources