Combining Signin & Signup policy with a resource owner password policy - azure-ad-b2c

I currently have two different policies for letting the users get the token - one for the interactive flows such as the authorization_code flow and another for resource owner password flow. There is another layer of APIs that we provide above the B2C which proxies the request to B2C for authentication. Based on the grant_type in the request, we are able to redirect to specific custom policy for getting the token. But, redeeming a refresh token also requires that we use same the policy that we use to get the token. The clients won't know which policy to use because they don't directly consume B2C.
Now I am trying to combine Resource Owner Password policy with the interactive policy to achieve this so that we only have one policy. This seems possible for the most part, except that there is no definite way to differentiate or identify the grant types. The claim resolvers such as {OIDC:GrantType} or {OAUTH-KV:grant_type} don't seem to be provided by B2C.
Is there any claim resolver that I can use to identify the oauth flow within the B2C policy?
Is there any other way to combine the interactive flow with ROPC flow?
Thanks for any input,
Anas

Send a custom query parameter storing the grant_type from your forwarding API so that you can read it using OAuth2 key-value parameters.
Eg.
API forwards to the ROPC flow using {authorization url}&custom_query_param=grant_type
You read the grant_type value using the {OAUTH-KV:custom_query_param} claim resolver.

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

Does B2C have a way of extracting form posted fields from an external identity provider?

We have a B2C setup using custom policies that authenticates against Apple Id as an external identity provider. This all works, and we are able to get the email claim. However, the first name/last name fields from Apple are not made available in the JWT token and therefore are not in B2C as claims.
They are, however, presented to B2C as a posted form parm called 'user' during the first-time authentication. This is obviously a non-standard way of using the OpenId Connect protocol.
Does B2C have a way of extracting form posted fields (or is it on the roadmap)? I see it is possible to get query string parms via a claims provider when using the OAuth protocol, but I don't see the same for OpenId and posted form parms.
The OpenID Connect technical profile maps claims from the ID token which means that additional authorization response parameters can't be referenced.

ADB2C identity experience framework : access token use just after an authentification

we are using lots of ADB2C built-in policies and wanna now switch on custom policies thanks to the Identity Experience Framework.
One of our use-cases is: make some calls (from the policy) on endpoints (that are protected by access token) just after an authentication (signup or signin). For example : just after the signup we would like to call an api for the privacy policy management. In order to have it working, we need to have the access token.
Is there a way, thanks to custom policies, to call an http endpoint with the access token just issued right after the authentication ?
When an access token or id token is generated by Identity Experience Framework (IEF), it signifies that all requirements of the user journey were met. That is, if the user journey required some privacy policy management and user needed to consent to it, only then would the access token or id token be generated.
The scenario that you are mentioning could be achieved by IEF calling the privacy policy management API using service-to-service trust and passing user's identity by other means, such as objectId in header or in the body.
Because IEF is directly calling the Rest API, it is unclear how IEF generating a token and sending that to the Rest API is more beneficial than IEF making a request over SSL and providing user's data.

Can Azure B2C claims exchange be used for Access token?

I got the workaround to work to add claims to the token using a custom REST API, however I realized this is the Id token and not the Access token. I need the custom claims to be the Access token to use for authorization in the service.
I haven't inspected the Access token yet but are these claims also inserted into the Access token?
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-custom-rest-api-netfw
Yes, custom claims come back when requesting access tokens. The only difference in the list of claims is the scp claim. The scp claim is only returned on access tokens.
Unfortunately, the Claims in ID and access tokens documentation doesn't discuss this.
You can quickly verify this via the Run Now feature in the Azure Portal. See this SO answer.
Sample access token w/ a custom claim
I am using custom claims in my Azure Active Directory B2C tenant where I registered two applications (UI and API). The UI passes the access_token to the API and I am able to retrieve the custom claims there. I guess this should be also true for custom claims using a custom REST API.
If not, It must be possible to setup:
... The return claims can be stored in the user's Azure AD account,
evaluated in the next Orchestration Steps, or included in the access
token
If your question is "Can I get the user's access token from the federating IdP such as Azure AD, facebook etc"? The answer currently is no. You can vote for this feature here.
https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/15334347-return-social-idp-s-native-access-tokens-back-to-t

Resources