JHipster - Single Page Application - OAuth2 / OIDC and access token location - authentication

Note that I'm quite new with OAuth2 and OpenID Connect so I may be a little bit confused. AFAIK, the recommanded authentication flow with OAuth2 in 2021 is Authorization Code Flow. I have already read the RFC 6749.
I have initialized a project using JHipster (v6.10.5, not the v7) with this configuration:
Which type of application would you like to create? Monolithic application (recommended for simple projects)
Which type of authentication would you like to use? OAuth 2.0 / OIDC Authentication (stateful, works with Keycloak and Okta)
Which Framework would you like to use for the client? React (i.e. a SPA application)
I'm wondering why is the JHipster's implementation stateful? (i.e. using HTTP session cookie JSESSIONID ; access token and refresh token are stored on the backend-side and NOT on the browser-side).
Why don't they make the browser acting as an OAuth 2.0 client to perform the authentication and storing the access token and the refresh token on the browser-side?
I don't find any explanation on the JHispter security page.
Beside, this blog mentions a schema that explains the OIDC Authorization Code Flow with a Public Client / SPA.

To complete Matt Raible comment, from OAuth 2.0 for Browser-Based Apps - draft-ietf-oauth-browser-based-apps-07 and ยง6.1. Browser-Based Apps that Can Share Data with the Resource Server:
[...]
An additional concern with handling access tokens in a browser is that as of the date of this publication, there is no secure storage mechanism where JavaScript code can keep the access token to be later used in an API request. Using an OAuth flow results in the JavaScript code getting an access token, needing to store it somewhere, and then retrieve it to make an API request.
Instead, a more secure design is to use an HTTP-only cookie between the JavaScript application and API so that the JavaScript code can't access the cookie value itself. Additionally, the SameSite cookie attribute can be used to prevent CSRF attacks, or alternatively, the application and API could be written to use anti-CSRF tokens.
[...]
However, I think the use of HTTP-session and OAuth2 token on the backend-side may complexify the management/implementation of some issues as we have to handle different timeouts:
idle timeout for HTTP session between the browser and the backend
expiration timeout or maximum lifetime expiration for the refresh token that is stored on the backend side
...
I'm now wondering how to provide a user-friendly experience, when some borderline cases happen. E.g: when the refresh token has expired on the backend-side but the end-user is still connected as the HTTP session between the browser and the backend is still valid.

Related

When an Oauth provider is used to delegate authentication, then does the appserver return any token to the caller?

In Oauth and Openidconnect, the appserver endpoint invocation starts the Oauth flow and the app server gets the token from the auth server and is able to pass the token to resource server to access resources (delegation) on behalf of the resource owner.
The token exchange happens between the app server and resource server, and the token never arrives at the end users browser.
I'm working on a web api (aka app server) that will be consumed by a mobile app. There is no other server involved. Presently the login endpoint returns a signed JWT token to the user if correct credentials are supplied (validate against the db). User places this token in the header of the subsequent request.
Assuming I don't want to have a user db and validate logins, and instead delegate the auth check to another service like azure b2c or firebase (that use the Oauth), then I assume the flow is like given below:
Api registered the firebase/azure b2c (let's call this the provier) clientid, secret.
User invokes login endpoint of my api
The api invokes the provider's Oauth flow.
User gets popup to authenticate with the provider.
Eventually the provider will send the token (containing the claim like username) to the api (aka app server)
Does the user get back any token? Otherwise, when the user makes subsequent endpoint calls, then how is the endpoint able to identify who is this user and whether he is already authenticated?
Although it is okay to send back the access token to the user , but from the security best practise 's point of view , it is better not to do it which I quote the reasons as follow from this:
Because of the issues outlined above, the best security recommendation
for an SPA is to avoid keeping tokens in the browser at all. This can
be achieved with the help of a lightweight back-end component, often
described as a Backend-For-Frontend.
The backend component can then be configured as a confidential OAuth
client and used to keep tokens away from the browser. It can either be
stateful and keep tokens in custom storage, or stateless and store the
tokens in encrypted HTTP-only, same-site cookies. Whichever variant is
chosen, the backend component creates a session for the SPA, using
HTTP-only, secure, same-site cookies, thus enabling a high level of
security. Such cookies cannot be read by scripts and are limited to
the domain of the SPA. When combined with strict Content Security
Policy headers, such architecture can provide a robust protection
against stealing tokens
Also from here ,they suggest for mobile app 's OAuth2 best practise , it should perform the OAuth flow inside a system browser component.

How to send a JWT from my back-end server to my front-end after Google OAuth2 Authorization flow

I am creating an application with a React front-end and a Java Spring Boot back-end.
My login flow looks like this:
A user clicks on login on the front end
User is redirected to the Google Oauth authorization endpoint on my server
OAuth 2.0 Authorization flow happens: User is redirected to Google and logs in. Google interacts with my server first exchanging an authorization code and then a JWT access token. My server now has the JWT access token for the user.
ISSUE: I now need to redirect the JWT token to my React front-end so that the token can be saved and used every time the user wants to request access to a protected resource on my server.
Is there now an industry standard/best practice for redirecting the token to my React front-end from the server?
There are similar questions on this subject on Stack Overflow, however they are at least 3 years old, e.g. How to provide frontend with JSON web token after server authentication?
Since then the implicit flow has been deprecated, storing JWTs in local storage is no longer recommended, and https://datatracker.ietf.org/doc/html/rfc6750 explicitly discourages passing bearer tokens to the front end in a redirect URL.
I was wondering if anyone knows of an up to date solution for this problem.
There's a draft IETF BCP for OAuth 2.0 for Browser-Based Apps - see here. Basically, it's very similar to native mobile apps using authorization code with PKCE (proof key for code exchange).
FWIW I agree implicit flow shouldn't be used, but IMO you shouldn't be using authorization code flow without PKCE, as this flow is for server side rendered web apps.
EDIT - Auth0 (one of the most popular CIAM solutions on the market) docs say the same thing - see here.
If the Client is a Single-Page App (SPA), an application running in a
browser using a scripting language like JavaScript, there are two
grant options: the Authorization Code Flow with Proof Key for Code
Exchange (PKCE) and the Implicit Flow with Form Post. For most cases,
we recommend using the Authorization Code Flow with PKCE...
Don't.
You seem to mix 2 issues here.
First, you would like to use OIDC for authentication in your SPA. For this you would use OIDC Implicit Flow or Authorization Code Flow with PKCE.
Second, you would like to delegate authentication to google instead of doing it yourself. Basically this is known as federation - you trust external Identity Provider.
The full-blown version would be to setup your own Identity-Provider server (like e.g. keycloak) and configure federation to google there. Your SPA would initiate OIDC against your Identity Provider and wouldn't even know that google did the authentication. You could also easily add further Identity Providers (e.g. facebook) if necessary.
An easier workaround would be to initiate OIDC login from your SPA directly to Google. This way your SPA would receive token directly from google and you would need to protect your own backend as a resource-server accepting and validating those tokens. Adding further Identity-Providers like facebook would be a challenge.

OAuth2 flow in full-stack NestJS application

Yet another OAuth2 question that isn't quite covered elsewhere.
I'm using NestJS backend, React frontend, Passport and my own DB for authentication. Trying to add an
OAuth2 identity provider (Google).
I configured my NestJS app as an OAuth Client. After logging in I'm receiving the callback at which point I have an access_token and the requested user details extracted from the payload of the id_token. This is encapsulated in a class extending PassportStrategy(Strategy, 'google') and an AuthGuard('google') and much of it is handled automatically. Code here.
At this point however, I need to maintain an authenticated session between backend (NestJS) and frontend (React). I suppose I need a JWT, but I'm wondering about the best approach:
Can I use a token provided by the IdP (e.g. id_token or access_token)? So that I don't have to worry about issuing tokens myself. I.e. the frontend receives the token (either from backend, or the IdP directly), sends it on every request, backend verifies it with the IdP on every request (verifyIdToken or getTokenInfo of google-auth-library).
One drawback here is the extra network request every time. I'm not sure if there's a need for that because the IdP is only used to identify the user, not for access to other resources. Another drawback is that I need to store a refresh token and handle when the token expires (get new one, update it on the frontend).
So alternatively, could I just issue a JWT myself and not worry about checking in with the IdP? Once the JWT expires I'd need to prompt the user to log in again. In this case, I wouldn't need to store the IdP tokens. But is this good practice? One issue I can think of is that I won't detect if the user revokes access in the IdP (until the JWT expires).
I ended up issuing my own JWT tokens and managing User sessions in my app, as described in this article: OAuth2 in NestJS for Social Login (Google, Facebook, Twitter, etc)
probably my solution would be helpful.
you could access complete source code of my app that implemented with react typescript (redux toolkit rtk Query) and nestjs included of google oauth2 flow with passport.js. resource

Single Signon Tokens usage in multiple applications

I am currently working on a small SingleSignon application. This way, I can save time whenever i make a new project, because the login process is mostly in place from the beginning.
To start with i think I should mention that many off my applications are build on Angular, so I often have multiple applications in one project:
The Angular app (HTML / Javascript)
The REST API (Either PHP or .NET (doesnt really matter))
I have been reading up on OAuth2, JWT and so on, and I understand that:
1) the application authorizes with the SSO API.
2) the SSO API responds (if successful) with an access token.
3) Add the access token to the header, and i have now access to the SSO APIs
BUT
What about my own API that belongs to the application itself? (See the image below for better understanding).
The API for the application knows nothing about the token I recieved from the SSO API, and would of course reject it...
SingleSignon Authorization flow
How would you normally implement this?
Should the application API also ask the SSO api on every request, to validate the token, or how? What would be best practice?`
Thanks
/Dennis
After studying Auth0, I found out that if you are using Opaque tokens (croptographically random string, with no meaning), the token is being verified against the authorization server from the API, as I mentioned in my original post. If you are using JsonWebToken on the other hand, there is no need to contact the authorization server, but check validity of the token by its expiration and signature, AND audience should match the domain of the custom API
So therefore; If you have a custom resource / API, you can benefit from a selfsigned token like JWT, and define the custom resource url in the AUD grant of the token.
Then the resource can validate against the AUD grant.

How to authenticate users of ASP.Net Core website with JWT?

I am wondering, if JWT should be attached to the header of my request manually, how can I use JWT to authenticate the users of my ASP.Net Core website?
In other words, how can I tell my browser to attach the token in the header when sending the request to my server? Let us say the user of my website got this token from one of my website's API.
Or is JWT usable only for WebAPI (where I can manually build the request)?
There are different ways to use JWT tokens. Since JWT is just a token format, it does imply the method used for authentication.
However, JWTs are mainly used for Bearer authentication scheme, which requires adding a custom header to each request. Single page applications (SPAs) that create requests in JavaScript on the client to access API endpoints can do that which is why Bearer+JWT is used a lot in SPAs. SPAs also benefit from the embedded JSON format since they can read expiration dates and other information (claims embedded in the token, ID token contents obtained via OpenID Connect etc.).
For "traditional" server-rendered views and links, using JWTs is hard since they'd have to be set as cookie or made part of the URL (practically impossible because of URL length restrictions). ASP.NET Core 2.0 does not contain any JWT-based cookie logic but it is possible to create a custom implementation using JWTs as cookies. See this GitHub project and related blog post for a sample implementation. Note that the only benefit of using JWTs in cookie authentication is that the server doesn't have to persist cookie information and share cookies across multiple instances.
To sum up the current state:
Prefer default cookie authentication when you use server-side rendering and links to avoid creating custom cookie implementations.
Prefer JWT bearer authentication if you have single page applications (SPAs) apps that build requests in javascript/typescript on the client.