azure-ad-b2c - How to prevent reuse of Oauth Authorization Code? - azure

I'm using the OAuth 2.0 authorization code flow , but I noticed that I'm able to reuse the same authorization code and the server responds with a new id token.
And as per OAuth 2.0 specifications, The client MUST NOT reuse the same authorization code (https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2)
Am I missing any settings in my policy? The only documentation that I found about code authorization code flow in AzureB2C is the following: https://learn.microsoft.com/en-us/azure/active-directory-b2c/configure-tokens?pivots=b2c-custom-policy#authorization-code-lifetime
Edited:
I generated the auth-code by using below endpoint:
https://tenant.b2clogin.com/tenant/policy/oauth2/v2.0/authorize?client_id=clientid&response_type=code&redirect_uri=https://jwt.ms&scope=openid&response_mode=query&code_challenge=codechallenge&code_challenge_method=S256
I generated the access token by using parameters like below:
But still able to generate tokens using same code
Here's my new app:

If you are not using a nonce claim, this expected behavior due to a known limitation with B2C.
According to the RFC (6749) - The OAuth 2.0 Authorization Framework
The authentication code should be used one time.
With standard Azure AD, a fix was released in 2018:
Azure Active Directory breaking changes reference | Microsoft Docs
This is because B2C is stateless and does not follow the OTP RFC standard here. Standard Azure AD made engineering provisions to track and invalidate AuthZ codes back in 2018, but Azure AD B2C has not completed this work yet. B2C would have to become a stateful service and this is a significant investment. So while this is a known issue, this work is not completed at this time.
A workaround is to use the nonce claim.
See also: B2C nonce

I tried to reproduce the same in my environment and got the error like below when I tried to reuse the auth-code:
I created an Azure AD B2C application and added SPA redirect Uri like below:
I generated the auth-code by using below endpoint:
https://tenant.b2clogin.com/tenant.onmicrosoft.com/policy/oauth2/v2.0/authorize?
client_id=ClientID
&response_type=code
&redirect_uri=RedirectUri
&response_mode=query
&scope=scope
&state=state
&code_challenge=codechallenge
&code_challenge_method=S256
I generated the access token by using parameters like below:
https://tenant.b2clogin.com/tenant.onmicrosoft.com/policy/oauth2/v2.0/token
grant_type=authorization_code
&client_id=ClientID
&scope=scope
&redirect_uri=redirectUri
&code_verifier=codeverifier
When I tried to reuse the code, I got the error as below:
Note that: By default, the auth-code lifetime in Azure AD B2C is 10 minutes, and it cannot be changed.
By default, Azure AD B2C will not generate the token if the auth-code is already used.
Make sure to use https to transmit the auth-code.
While generating the auth-code make sure to receive the prompt while signing in by using prompt in the authorize endpoint.
If still the issue persists, try by registering a new application and check.
Reference:
Updates and breaking changes - Microsoft Entra

Related

AzureADB2C Client Credentials Grant with Client Assertion as Opposed to Static Secret

I have a requirement to provide API to our consumers. The intention is to secure the API using AzureAD B2C - Client Credential Grant flow.
I have created a custom policy on B2C tenant that provides the access token. Things work fine with the clientId and Secret authentication method.
I now want to secure the OAuth2 conversation further by allowing the client to use the signed client_assertion as opposed to static client secret using their protected key. I have uploaded the public portion of the key into the relevant app registration.
Unfortunately, consuming the /token endpoint with the signed client_assertion results in an error.
REQUEST
https://tenant.b2clogin.com/tenant.onmicrosoft.com/b2c_1a_demo_clientcredentialsflow/oauth2/v2.0/token
grant_type=client_credentials&scope=https%3A%2F%2Fapi%2F.default&client_id=d5339984-e6c7-457a-9ef9-21fb6e3e6c59&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJo
RESPONSE
HTTP/1.1 400 Bad Request
{"error":"invalid_request","error_description":"AADB2C99027: Policy 'B2C_1A_Demo_ClientCredentialsFlow' does not contain a AuthorizationTechnicalProfile with a corresponding ClientAssertionType.\r\nCorrelation ID: 5eb76fa5-c919-4877-a722-0d38408e18c6\r\nTimestamp: 2023-01-19 07:38:25Z\r\n"}
Can someone please tell me if B2C is intended to support client assertions? Metadata JSON on the policy returns only the following two authentication methods:
"token_endpoint_auth_methods_supported": [ "client_secret_post", "client_secret_basic" ]
Is it possible to include private_key_jwt as a supported authentication method using custom policy configuration? Is it possible to configure the AuthorizationTechnicalProfile for the policy with a corresponding ClientAssertionType?
I hope that I have explained the problem well enough.
I have tried various strategies, incluling the use of AAD token endpoint, login.microsoftonline.com with the B2C tenant Id. Using that endpoint, the custom policy on B2C is completely ignored, therefore generating a vanilla token with none of my curated claims.
TLDR: As of June 2022, Azure AD B2C does not support client assertions.
This issue on Github asks for documentation for error number AADB2C99027. In the course of the discussion, a member of the team states
Unfortunately, we decommissioned client_assertion flow because it didn't follow OIDC spec – So we shouldn't be documenting the error.
From that, I take that there are no plans to support client_assertion flow.

How to add a secret to "Resource Owner Password Credentials" B2C based app registraion on azure

I have an app registration on Azure that is being used to authenticate requests using the ROPC flow, so that we can mimick a real user access token and test our APIs. This is working, but to make this more secure we would like to be able to say a secret is required in the request.
This is not default for ROPC as it wasn't intended to be used with secrets (note - we cannot use client credentials for this part of testing we are doing).
The app registration is used along with a B2C user flow setup along side it. I don't believe this to be too relevant for this issue, but I could be wrong.
Currently the working call is as follows -
On azure to allow the ROPC flow you need to set the application to allow public flows.
I believe this setting stops any form of client secret or certificate being required in the request.
The microsoft docs seem to suggest it is possible to add a secret to ROPC calls and make them required but i can't figure out a way of doing it while having the above "public" azure setting set to true. With that off you get an error saying that the resource owner flow is not allowed due to it being private.
This is part of the Microsoft docs - https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc which seems to suggest you might be able to make the app private, I just can't see how while allowing the flow.
This link you mentioned is about Azure AD, but not Azure AD B2C. So there are two methods to get the access tokens with different formats. In addition, it's more secure for you to use authorization code flow in Azure Active Directory B2C.
One is following AAD Docs with your AAD B2C directory, see the explanation. Note: scope doesn't support application-id, it's related to the permissions in API Permissions.
POST https://login.microsoftonline.com/{b2c-tenant-name}.onmicrosoft.com/oauth2/v2.0/token
client_id={b2c-application-id}
&scope=openid offline_access
&username={username}
&password={password}
&grant_type=password
&client_secret={client_secret, if your app is not a public client}
[Recommend] Another is testing ROPC flow in Azure AD B2C. client_secret is not in the parameters, so it is not required whether it is public or not.
https://{b2c-tenant-name}.b2clogin.com/{b2c-tenant-name}.onmicrosoft.com/{B2C_1_ROPC_Auth, name of ROPC flow}/oauth2/v2.0/token
username={username}
&password={password}
&grant_type=password
&scope=openid offline_access {b2c-application-id}
&client_id={b2c-application-id}
&response_type=token id_token

Is the Azure Active Directory Access Token valid for ReAuthentication with a Custom WCF Policy?

I am retrieving an Azure AD access token using MSAL.js at the client and passing it as Authorization header to web api hosted in WCF API Management. But I get an error along with all the proper response as well my username and email
Cannot validate access token. IDX10501: Signature validation failed.
Key tried: 'System.IdentityModel.Tokens.X509AsymmetricSecurityKey
The API is a WCF service configured with a custom policy binding for OAuth with the metadataEndpoint or even the v2 version https://login.microsoftonline.com/{tenantid}/.well-known/openid-configuration .
I guess the Azure AD Access token that I have is not meant for validating authentication again.
My guess I might be either missing permissions on the App registration but I couldn't find an API permission for exact authentication/authorization.
I believe with new Azure AD , we cannot authenticate the earlier manner by just passing a token and need to use MSAL standard libraries.
Could someone shed some more light on this.
I used an ID Token and then it worked. You get 2 tokens when authenticated so the ID token seems to work.

How to implement authentication and authorization using MSAL.net

Please help me.
To login into Azure active directory how to use MSAL.Net library in my login page of my website.I am seeing very big samples online but I didnt find small peace of code which makes me to understand MSAL.
MSAL Library is just an implementation for enabling developers to acquire tokens from the Microsoft identity platform endpoint.
If you want to use MSAL to acquire a token, you need to:
Register an application in Azure AD.
Add target API, and grant consent to select permissions.
Generate a secret key.
Then you can get a token as Acquire a token and call Microsoft Graph API.
However, I think what you really want is to integrate AAD. You can easily enable AAD authentication for your .NET web application. It uses OWIN middleware.
If you are using a aspnet or aspnetcore, you can get the necessary code needed to sign in your web application with your Azure AD tenant just by following steps.
Create the sample from the command line
Note that MSAL.NET is a token acquisition library (for services like MS Graph and such) that can optionally sign-in users as well. the sign-in code is present in the aspnet and aspnet core SDKs

Azure AD metadata and userinfo does not support CORS

I was working on a JS app which talks to Azure AD app using OIDC. Here is the flow of authentication and validation -
Redirect user to common login end point
Get access token, id_token etc. on callback url
Validate response with jwt keys retrieved from discovered url - https://login.microsoftonline.com/common/discovery/keys
Get user info from discovered userinfo url - https://login.microsoftonline.com/common/openid/userinfo
Store the information in local / session storage, depending upon settings.
The problem with Azure AD is, we can not complete step 3 and 4. Both the urls do not support CORS. We are not able to validate the tokens we get and can't retrieve the user information.
Is there any better way to get userinfo in Microsoft's implementation of OpenID for Azure AD?
You are correct, Azure AD does not support CORS for either the metadata URL or the keys URL.
The general guidance is to not validate the id_token since you should only be using those claims for display purposes and not to drive any core functionality.
For core functionality (aka API calls) you should use access_tokens which should be validated by your back end which does not need CORS enabled endpoints.
You'll see these principals in action in the Azure AD SPA sample where authContext.getCachedUser() in adal.js is used to obtain the read the user and its claims without any validation.
If you want more validated user info, the guidance is to call the Graph to obtain user info via the Microsoft Graph's /me endpoint. You can see this pattern in the Azure AD Xamarin Sample.
You can vote for the request in the Azure AD feedback forum: Add CORS support for discovery and json web key set endpoints.
I ran into the same problems a while ago and the solution to these problems was to double hop the JWKS and UserInfo calls via an API.
I also used the certified and widely respected OIDC Client library, which has features for SPA silent token renewal and id token validation.
Personally I like to keep my apps coded in an Open Standards manner as much as possible, rather than being locked into one vendor.
PS. If you think this type of solution would work for you, here is a GitHib Sample and some documentation.

Resources