Unauthorized on Web API when updating mobile app to use ROPC to request access token - authentication

I updated my mobile app to request an Azure AD B2C token using the ROPC policy. When I send the token as a Bearer token, same as I did with the Sign Up Sign In policy, I get an unauthorized error.
One thing I had to do was request the token via HttpClient because the new Microsoft.Identity.Client package does not have the AcquireTokenByUsernamePasswordAsync() function.
In the Web Api, I updated the TokenValidationParameters to have the new ROPC policy as the new AuthenticationType but that does not work either.
What updates do I need to make so that I can use the access token I receive back to authorize on my api?

What I did to solve this is set the API ClientId to be the same as the mobile app ClientId which solved the issue for me.
This seems like it is not the correct way to solve this issue, but I could not find another solution at this time.

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.

Getting refresh_token server-side (sessionToken) with Okta

We wish to use our own httponly strict cookie with access and refresh token in it for our microservices architectures.
We are primary using OKTA Authentication API to log users with our own custom Sign-in page.
We were able to get the access_token on the authorize endpoint using the responsetype=token with sessionToken and redirecting the result as a form_post on our back-end endpoint.
I was unable to retrieve the refresh_token despite adding the offline_access in the scope even if it is checked in my okta application setting.
I don’t want to use resource password flow since we prefer using sessionToken which will work with multi factor if needed in the future.
I also try using the code flow and redirecting the result on our back-end but since the code flow is client-side it’s return this error "PKCE code verifier is required when the token endpoint authentication method is ‘NONE’." This error occur even if we choose a .NET application
How can we retrieve the refresh_token server-side with Okta?
Responded to your post here https://devforum.okta.com/t/getting-refresh-token-server-side-sessiontoken/12419/3.
Aside from making a call directly to /token with your access token you can also check our Early Access feature called Refresh Token Rotation. Let us know if this helps!
I was able to use the CODE flow and redirect from server-side to the authorized endpoint like so:
https://{YOUROKTADOMAIN}/oauth2/default/v1/authorize?client_id={YOURCLIENTID}&response_type=code&scope=openid%20offline_access&response_mode=query&redirect_uri={YOURSERVERSIDEGETURI}&state={Guid.NewGuid()}&sessionToken={SessionToken From Auth API}
This call will post back to my same server, so i can handle token myself and create my own cookie.

Oauth + SPA + API backend

I'm setting up a service which needs to authorize against an existing Gitlab as OAuth Provider.
The service is a SPA which gets served by a webpack dev server in dev mode and a nginx server in production mode.
I'm also setting up an external API which should handle the Database and make request to the given gitlab instance (for example pull repos).
My SPA is authorizing against the Gitlab OAuth with the implicit_grant flow and is getting an access token. Currently I pass the access_token after the redirect to my API backend and there I get the Gitlab userid and username via a request to the gitlab instance with the access_token. With these I generate a jwt and send it to the client (SPA) and save it there so I can authorize my API with this JWT.
How would I handle the initial access_token in my backend (cause I need the token to make gitlab calls)?
Currently I'm thinking about writing it to the user in the database and get the user everytime he makes a request (normal passport flow), so I also have the token. But what if the token gets invalid or expires?
Should I use an interceptor in the backend and if the token is invalid (gitlab would give me a 401) redirect the 401 to my client, let him get a new token and pass it back to the backend, generate a new JWT, send this again to the client and let him do the same request as original reuested(via interceptor, too)?
Or should I just redirect the 401 to my client, let him get a new token, let him post this token to for example /renewToken and save the token to the database and use the old JWT?
Hope someone can help me unserstand this flow.
The Credential Management API should be what your looking for on the client. That will retrieve the id and access tokens to that you can compare access tokens with your server/ap and then validate the id token.
Haven't seen a Git example but there are Google and Facebook examples.
You could let the user send the initial access token and your backend API will just act based on the initial access token. Seems to me that it is not necessary to produce another JWT token in this case.

Generate Access Token and validate against IdentityServer4 through Azure API Management

I have an external endpoint which is going to hit the Azure API gateway and that would route it to the backend API which is protected by IdentityServer4 authorization.
I am getting the access token if I hit it through the Postman client with the interactive UI from IdentityServer.
Is there a way I can get the access token required from the Azure API Management to validate against the IdentityServer4 and append it to the header in the request to the backend API?
Yes it is possible to achieve it through custom policy. You can ask your external API-Client/Consumer to paas in credentials in heaser, and then you write a policy inside inbound to can read those user credentials and do a API request (similar to your postman) and get the access token. You can then append the same token and let your request gets forwarded to backend API.
As per your problem statement, this should work. In case not, you might have to explain your scenario with more description/steps.
Here are some of the reference materials for you, I hope it helps.
https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies#SendRequest
https://learn.microsoft.com/en-us/azure/api-management/api-management-sample-send-request
Postman has a luxury of a human user seeing the UI and authorizing API access and IdentityServer4 to issue a token for Postman. There is no such luxury when call is being processed by APIM server, as you could send request for token to IdentityServer4, but who would be presented UI to authorize the action?
The only way is to provision some sort of secret to APIM (header, query, certificate) that would be recognized by IdentityServer4 to allow it issuing tokens for APIM. If such secred is available you could use send-request policy to make a call to IdentityServer4 and obtain required token.
Or make sure that every request to APIM has a token already.

Get refresh token with Azure AD V2.0 (MSAL) and Asp .Net Core 2.0

I've got access_token from Azure Ad V2.0 endpoint to call Graph Api. But I have to do some actions in the api on behalf of user. So I need refresh_token to renew my access_token when it'll expire.
Is there any way to get Refresh token using MSAL in ASP .Net Core?
In microsoft documentaion they're telling it's possible to do by requesting /token endpoint. But I couldn't find how to do it using MSAL.
MSAL .NET does not expose the refresh token, but rather keeps it internal and handles all token refresh and caching logic on the app's behalf.
The docs you're referring to are referencing the protocol itself that MSAL is completing on your behalf. It goes to the /token endpoint with an authorization code (after the end user signs in), and is issued an Access and Refresh token. The Access Token is valid for 1 hour, and when it's expired, AcquireTokenSilent will automatically use the refresh token against the /token endpoint to get a new access token.
I got a bit topsy-turvy on this, as well. Explaining a bit more based on my understanding.
For context, OAuth 2.0 code grant flow mentions the following steps:
authorization, which returns auth_code
using auth_code, to fetch access_token (usually valid for 1 hr) and refresh_token
access_token is used to gain access to relevant resources
after access_token expires, refresh_token is used to get new access_token
MSAL.NET abstracts this concept of refresh_token via TokenCache.
There is an option to serialize TokenCache. See Token cache serialization in MSAL.NET. This is how to preserve sign-in info b/w desktop application sessions, and avoid those sign-in windows.
AcquireTokenSilentAsync is the process by which refresh_token is used to get new access_token, but, this is internally done. See AcquireTokenSilentAsync using a cached token for more details and other access patterns.
Hope this clarifies on why TokenCache is the 'new' refresh_token in MSAL.NET, and TokenCache is what you would need to serialize and save. There are libraries like Microsoft.Identity.Client.Extensions.Msal that aid in this.
TokenCache is basically a JSON object which is served as byte array when you call SerializeMsalV3(). When you convert byte array to string, you will see both access token and refresh token. Then you can make a HTTP request to \token endpoint with this refresh token and grant_type: "refresh_token" body parameters.
IConfidentialClientApplication capp =
ConfidentialClientApplicationBuilder.Create(myClientId)
.WithClientSecret(myclientSecret)
.Build();
capp.UserTokenCache.SetAfterAccess((TokenCacheNotificationArgs args) =>
{
exchangeTokenCacheV3Bytes = args.TokenCache.SerializeMsalV3();
string jsonString = System.Text.Encoding.UTF8.GetString(exchangeTokenCacheV3Bytes);
});