Getting refresh_token server-side (sessionToken) with Okta - asp.net-core

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.

Related

How to "sign in with Google" (id_token) *and* receive a code/access_token for specific scope (for the backend)

I'm building an application where a user should be able to sign in with Google, but afterwards, the backend server needs access to some data from the users's account (analytics.readonly scope).
If I understand it correctly, this can be done with the "OAuth Hybrid Flow": An id_token and an authorization_code are returned on the front channel, but the sensitive access_token and refresh_token can only be retrieved on the back channel.
Yet, Google does not seem to provide this functionality.
I imagined that my frontend could receive both an id_token and a code as URL parameters after the Google OAuth flow. The React frontend would then POST both the id_token and the code to my Flask backend.
The backend would then 1) check the id_token, 2) exchange the code for a refresh/access token and return an authenticated session cookie to the frontend.
Now my question:
Can I use just the returned authorization_code to sign in my users? (i.e. instead of an id_token?) What are the security implications? In that case I could just continue with the regular Authorization Code Flow on the backend.
Is there a way, to retrieve both an id_token and an authorization_code from Google at the same time that I have not found?
Is there any other way to achieve what I want? (Sign in with Google for Frontend, secure retrieval of access_token/refresh_token that only the backend needs)
Thanks!
I would handle the token management on the backend instead of doing it in the frontend.
The authorization code is only used as part of the authorization code flow.The code is just a random token and does not contain any user info, so you can't use it to signin the user.
You can't get the id_token and authorization_code at the same time, why would you? Auth code flow is a two step process, so you always get a code first, that you then can exhange for the id/access tokens.
I would consider looking at this this great video for how to approach authentication for SPA applications.

Need to configure Spartacus3 with Auth0

I have to use Auth0 for the application and need to bypass Spartacus password login flow. I have gone through https://sap.github.io/spartacus-docs/session-management/#configuring-authorization-code-flow-or implicit-flow found that there is implicit flow to bypass login.
Tried with "authorizationserver/oauth/token" API hit manually and store token in local storage but getting other issues.
Can I know better approach to implement Auth0 in Spartacus and bypass password login flow.
Spartacus supports 3 flows with OAuth without any serious modifications required.
Password flow -> the default one. You login in spartacus form and the credentials are send to server and exchanged for access_token.
Implicit flow -> When you click login you are redirected to OAuth server login page. You put credentials there and after that you get redirected back to spartacus with access_token in on of the query params of the redirect url.
Authorization Code flow -> similar to Implicit flow, but in response you get code which then you need to send to oAuth server to exchange it for access_token.
To specify which flow you want to use you need to change the responseType config as mentioned in https://sap.github.io/spartacus-docs/session-management/#configuring-authorization-code-flow-or-implicit-flow
For Auth0 I would recommend going with Authorization Code Flow (as it's more secure than Implicit flow, especially with PKCE enabled).
Apart from the responseType you would need to set baseUrl in auth config to point it to Auth0 server (and I assume you have integration done in the backend that can verify tokens returned from Auth0). You might need to adjust few other config options as well, but you should be able to figure those out based on the problems you encounter.

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);
});