Blazor Webassembly JWT Authorization first steps - authentication

I have created a small .NET 5.0 Web API where a users can register/login to create/add/delete notes. The API is working fine, after the login I receive the JWT token in the response back.
Now I want to create a Blazor Webassembly website which will communicate with the API.
The problem I have is that I don't know where to start and what do I need to get the web page take the Token from the response and how to work with it to be authorized when doing API calls.
In the API i have used the IHttppAccesor to get access to the user data from the JWT token, is it similar to work with the token for the authorization.
Any suggestions what to use or where to start would be greatly appreciated!

Related

.Net Core MVC Client - Authentication over JWT service

I have two projects, one is the API, the other one is the Client to consume the API. Both are .net core 3.1. The API project has been developed inspired by this post:
https://jasonwatmore.com/post/2021/06/15/net-5-api-jwt-authentication-with-refresh-tokens#users-controller-cs
and it has JWT Authentication with refresh token and some methods with Authorize attribute.
My problems starts in the Client project. The API projects emits access token and the client should use it accessing the protected API.
I can authenticated in the API, but when the client receives token (access token and refresh token), it store it in authentication cookie and in the refresh token cookie.
My doubts are:
Is this approach correct?
how can i manage that the access token expires and use the refresh token to get a new one? Do cookies need to be regenerated?
In future development i will add Facebook auth and client auth.
If is needed more details or some implementation let me know.
Thanks in advance.

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.

How to secure Web API with Auth0 without exposing ClientId & ClientSecret to client?

I am creating a new .Net Core Web API that is consumed by a new React client-side app. Both the client-side app and the Web API are on different hosts and protected by Auth0. I set up both the client-side app and the Web API in Auth0, and then I created a machine-to-machine app in Auth0 to be able to communicate with the Web API silently (without a user interface). The security flow works like this:
User tries to access client-side app.
User is re-directed to Auth0 to provide credentials.
Auth0 authenticates the credentials and returns user info (including user ID + access token) to client-side app.
Client-side app stores user info in local storage for future use until it expires.
Any calls to 3rd party APIs are routed through my own Web API, so 3rd party API keys are sitting in a safe place on the server, not on the client-side.
User accesses a page that requires a call to my Web API but we don't have an access token for my Web API yet.
Client-side app reads the ClientId & ClientSecret (hard-coded values) from .env file and makes a POST request to Auth0 to fetch an access token for my Web API (this is Auth0's recommended way of getting the access token for the Web API silently except they don't specify where the ClientId & ClientSecret would be stored).
Auth0 returns an access token for my Web API.
Client-side app stores the Web API access token in local storage for future use until it expires.
Client-side app invokes my Web API with newly acquired access token as the bearer token in the header.
Web API receives the access token, authenticates with Auth0 and fulfills the request.
All of the above is working for me but I am concerned about storing the Auth0 ClientSecret of my Web API in the client-side app. Although it is not visible on the screen or in a cookie anywhere, any capable user would be able to get at it by inspecting the network traffic.
Many people on the Internet seem to be fine with storing 3rd party API keys in .env files while others advise routing 3rd party API access through your own Web API ... and I am doing the latter. But I still need the Auth0 ClientSecret to get to my own Web API and I cannot figure out a better place way to get to it without storing them somewhere on the client-side.
One last-ditch solution I can think of is to not protect my Web API through Auth0 and instead every call from the client-side app to my Web API should include something unique (like the user ID from Auth0) that can be validated by the Web API. Thankfully, the user ID from Auth0 will be stored in our database when the user is set up initially, so this is actually possible.
Does Auth0 have any other way for me to get the Web API access token without providing the ClientSecret given that I already have the client-side app's access token? I am curious to know how others have secured both their client-side app and their Web API through Auth0.
You are correct, you should not include the client secret in your client-side app. Do not use a client credentials flow, instead use a auth code + PKCE or implicit flow.
With that being said, Auth0 should handle most of that if you are using a library or SDK.
You have two options for getting the token:
When requesting the initial access token and ID token add the Web API as an audience and request the related scopes.
Make a silent request using the checkSession function for Auth0.js or getTokenSilently for auth0-spa-js
Take a look at this:
https://auth0.com/docs/architecture-scenarios/spa-api/part-3

Get external claims using Google AccessToken in Asp.Net Core API 2.1

I am using JSON Web Token (Bearer) as my default Authentication. I'm then using (Cookies) as my Authentication for Google.
I am using the default Google Authentication in Asp.Net Core API to get the AccessToken. I then pass that AccessToken to my Angular application in the Url, using a redirect. This is similar to how the ASP.Net MVC 5 Web API works. From there, I'm making a call back to my Asp.Net Core API to try and get the remaining claims. I'm making the call using the AccessToken.
Does anyone know how to access the external claims using the Google AccessToken? I know how to do this in the Asp.Net MVC 5 Web API, but Asp.Net Core is much different.
I can see external claims here. This happens during the OAuth process after the User Authenticates with Google. This is in my ExternalLoginCallback method.
var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
Here is some information that seems to be useful, but it doesn't specifically address third party Auth.
https://learn.microsoft.com/en-us/aspnet/core/migration/claimsprincipal-current?view=aspnetcore-2.2
If I call the API using the AccecssToken, in the header, and use HttpContext.AuthenticateAsync like so....
var result = await HttpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
I get this.
{System.Exception: No SecurityTokenValidator available for token: ya29.Glt5B_thgPhe8-FcR
Thanks in advance! Any help is much appreciated.
Here is what I ended up doing. Since I'm able to get the claims from the Cookie in my ExternalLoginCallback method, I went ahead and created a new JSON Web Token (JWT), added the extracted claims to it and then passed that over to my Angular application. Now, when I make the call back to my API, I'm able to read that Token and extract the claims using this line of code in my GetUserInfo method.
HttpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
Bottom line, since I could not read the Google AccessToken like I could in my ASP.Net MVC 5 Web API, I just went ahead and created a new JWT Token, added in the claims and used that.
By the way, I'm having to do all of this because I can not call my ExternalLogin method directly from Angular because of a known Cors policy issue.

Asp.net core JWT with Google OAuth

I'm new to asp.net core.
I'm trying to create a simple WEB API with asp.net which uses Jwt Token and Google OAuth.
About JWT, I've followed this tutorial and succeeded : https://stormpath.com/blog/token-authentication-asp-net-core
But I don't know how to do my authentication with Google OAuth in my WEB API system. What I think about is :
Because WEB API doesn't have view, a client app (Desktop App, iOS App) will get authentication code and exchange that code for access_token.
Web API receives access_token comes from client, send request to Google to verify the token and do authentication.
My question is :
Is my implementation correct?
How to implement it by code ?
Thank you,