Asp.Net Core API OpenId-Connect authentication with JWT token using IdentityModel - asp.net-core

I have an ASP.NET Core API as back-end for an Angular SPA front-end. I am using Cognito as an Identity provider and want to create an OpenId-Connect authentication using authorization code flow which would mean that all the secret credentials will be stored in back-end.
The authorization flow should be like this (standard OpenID Connect flow):
FE application calls /authorize endpoint and is redirected to Cognito hosted UI.
After entering credentials FE receives an authorization code.
FE calls BE with authorization code.
BE calls /token endpoint and receives accessToken and refreshToken.
BE Returns accessToken to FE and sets refreshToken as httpOnly cookie(for this not sure, I may store it in Redis cache).
Then, FE with each request will add Bearer AccessToken to authenticate. When AccessToken is close to expiration, it will be updated using refreshToken.
I was experimenting with this example but here application used an Asp.Net Core cookie for authentication and ignored accessToken and refreshToken. I was authenticated even after accessToken was expired. Also, there's not much documentation on how ASP.NET cookie works.
So, now I am thinking about having my custom BE endpoints and use IdentityModel helper methods but not sure if it is a good practice to handle authentication like this.
/Login - gets AccessToken and RefreshToken
/Refresh - updates AccessToken using RefreshToken. FE will call it manually when accessToken will be close to expiration.
So, is there a "recommended" way to handle this scenario nicely with IdentityModel without writing custom implementation?
Also, as far as I know, it is quite common to store refreshToken in httpOnly cookie which will be added to each request sent to BE but then I don't see the point of having an accessToken when I already have refreshToken added with each request.
Isn't it better to store refreshToken inside BE for performance and security reasons?
Authentication is a part of every application so I believe there should be some in-built framework functionality for authorization code flow as well.

You are describing a Backend for Frontend approach, which is a good architecture. Make sure you separate the specialist API that deals with OAuth from general business APIs.
RECOMMENDED WAY
Curity have an approach that provides state-of-the-art security for SPAs, here are some links:
Token Handler Blog Post
Code Example
Code Example Doc
We may add a .Net token handler at some point, but it should not matter what tech is used, since the idea is for the specialist API to be something you plug in rather than code.
STORING REFRESH TOKENS
My personal preference for SPAs is to use AES256 encrypted HTTP only cookies. This fits nicely with goals of avoiding OAuth plumbing in applications and enables the token handler to be stateless and easier to deploy + manage.

Related

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

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.

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

Authentication for hybrid flow for ASP.NET MVC client

I'm learning identityserver4 and can't understand some stuff.
Shortly: I want to authorize end-users with email and password on ASP.NET MVC client side (it will send user credentials to the token server to get tokens), and I don't want third-party clients to retrieve data from my API resources.
As I understood from the documentation:
implicit flow is used for SPA (js clients) and uses id_token to authorize users. I can store id_token in my browser.
client credentials flow is used for trusted apps (like ASP.NET MVC client) to authorize clients and uses access_code. I can store access_code inside my app.
So looks like I need a hybrid flow.
In the documentation I read that I need to use AddOpenIdConnect() method and
Technically the tokens are stored inside the properties section of the cookie.
So my questions:
If the id_token can be stored in the browser, why is it not safe to store the access_token there too ?
As the docs state, the tokens are stored inside the properties section of the cookie. It's confusing, because some guides says, that it's not safe to store access_token there. So where I should store access token in my ASP.NET MVC client?
Am I right, that AddOpenIdConnect() configures my ASP.NET MVC app to retrieve access_token automatically from the token server? And if yes - in which moment should I authorize users with email/password and how to combine all tokens inside one JWT on my ASP.NET MVC client's backend when I will send requests to api resources ?
Today you should not use the Implicit Flow and it has been deprecated as of Oauth 2.1. What you should use is the authorization code flow with PKCE. PKCE is a security enhancement for the authorization code flow.
So as of OAuth 2.1 you only have two main flows:
Authorization code flow, for a MVC client to login a user to the client
Client credentials flow, for API->API communication where no human is involved.
To answer your questions:
If the id_token can be stored in browser, why it's not safe to store access_token there too ?*
The ID-Token is only used to create the initial user session and after that you can throw it away. It also only have a short life time of 5 minutes by default in IdentityServer.
As the docs state, the tokens are stored inside the properties section of the cookie. It's confusing, because some guides says, that it's not safe to store access_token there. So where I should store access token in my ASP.NET MVC client?
The tokens can be stored in your session cookie in ASP.NET Core and that's secure. It's protected / encrypted using the Data Protection API. However, the cookies can grow in size quite a lot if you do that.
Am I right, that AddOpenIdConnect() configures my mvc app to retrieve access_token automatically from the token server? And if yes - In which moment I should authorize users with email/password and how to combine all tokens inside one JWT on my ASP.NET MVC client's backend when I will send requests to api resources?
AddOpenIdConnect only handles the initial login and retrieving the first ID and access token. It does not handle refreshing of the access token using refresh tokens. For that you can add the IdentityModel library.
Today when you use the auth code flow, you redirect the user to IdentityServer and you let the user login there instead of passing the username/pwd from you browser to identityserver.

Implement authentication with token bearer and not cookie

How is it possible to implement authentication (and authorization) without cookie and only bearer token in ASP.Net MVC Core for all pages?
Can we still use ASP.Net Identity?
No, you can't use bearer token with MVC Views. Only with WebAPI-esque calls (which are called by JavaScript/Ajax calls), because for Bearer Token you need to pass a header containing the bearer token within the HTTP Request.
Also neither ASP.NET Core MVC nor ASP.NET Core Identity provide a mechanism to generate JWT or opaque/refresh tokens. You need a 3rd party library (ASOS, OpenIddict or IdentityServer4 - or write your own middleware).
General approach is using Cookies for MVC (+AntiForgery Tokens - these are important to prevent Cross-Site Forgery Requests (XSRF) attacks) and bearer for WebAPI (there are security concerns running Ajax/Rest calls with Cookies, as you can't easily protect then like you can do MVCs with AntiForgery tokens). In doubt, google about the terms ;)
Does it makes sense to you?
You could store the JWT in a cookieless Session - see Asp.net mvc 4 - Need to use sessions but can't use cookies
That sort of defeats the purpose of having JWT though.
You could ensure the JWT is a URL param in every link, and then override Application_AuthenticateRequest to find that in the URL and manually assign the identity to the context. see answer How to use JWT in MVC application for authentication and authorization?
Having multiple links with sizable JWT token data would add up. Also if one is missed in a chain of links, then the JWT would be "dropped". It's possible to save the JWT in the client-side sessionStore and have javascript dynamically add the JWT to links as they're clicked.

Authentication and Authorization in asp.net core WEB API

I am new in asp.net core and want to implement authentication and authorization in WEB API 2 project. I am little bit confuse to use basic authentication, bearer token, JWT token or any other. please suggest more preferable
Thanks
Basic auth is as the name suggests, very basic and not very secure, it uses base64 encoding of the username and password so you must use HTTPS if you use it, but best is not to use it at all.
A bearer token is a type of token which effectively gives access to a resource to the "bearer" of the token. Both basic and bearer are used in an HTTP Authorization header.
You can have different formats of bearer tokens, one of which is JWT - JWT is the industry standard so I recommend you use it, and therefore you'll be using bearer tokens.
This article is a good starting point to look into all this in the context of asp.net core. See also this video series and this article goes into more detail about JWT validation.
Edit
To answer your questions in the comments:
OAuth is a standard for users to delegate permissions to apps or websites to access their resources, for example when you allow some web app to post on your behalf to your Facebook feed. Various tokens are used in this process and they're very often JWT. OAuth2 adds authentication via OpenID Connect.
OWIN on the other hand is a standard for web servers which decouples IIS and ASP.NET with the aim of allowing ASP.NET to run on other web servers which implement OWIN and other frameworks generally to run on OWIN compatible servers if those frameworks are OWIN compatible.
Auth0 is an identity platform which can do OAuth and allows you to use JWTs, generally it handles your identity and SSO. IdentityServer is another identity platform with some similar features.
I'd still recommend starting with the articles I linked at the top, don't worry too much about OWIN, and read more about OAuth to determine if you really need it. If you do, I'd recommend IdentityServer.
ASP.NET Core 2.0 and above Web API authentication and authorization
Bearer type JWT Token based authentication
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
Please implement as following below post
https://fullstackmark.com/post/13/jwt-authentication-with-aspnet-core-2-web-api-angular-5-net-core-identity-and-facebook-login