Error when obtaining token - azure-ad-b2c

I'm trying the sample code NativeClient-Headless-DotNet.sln against my B2C tenant.
When I attempt to execute the command:
result = authContext.AcquireTokenAsync(todoListResourceId, clientId, uc).Result;
using an existing username and password, I get this exception:
InnerException = {"unknown_user_type: Unknown User Type"}
As far as I know, I've set-up all the values correctly in Web and App config (I'm using the same values that I use in my Graph API project, which works OK).
Any ideas why this should happen?
Are accounts created with:
userType.type = "userName";
found by this method?

Currently, Azure AD B2C doesn't have any direct support for this.
However, work to support for the Resource Owner Password Credentials flow in Azure AD B2C is in-progress.
This new feature will enable a desktop application to collect a user credential and POST it to the B2C tenant for validation.

Related

Change Azure B2C account password on behalf of a user

I'm trying to change the password of a user created in my Azure B2C Tenant. I'm using Microsoft.Graph C# SDK to do API calls.
First I create GraphServiceClient by providing details of my tenant:
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential("tenantId", "clientId", "clientSecret", options);
_client = new GraphServiceClient(clientSecretCredential);
Then I use the built-in method of a client to change the user's password:
await _client.Users["userId"].ChangePassword(currentPassword, newPassword).Request().PostAsync();
But I get following error:
Microsoft.Graph.ServiceException: Code: Authorization_RequestDenied
Message: Access to change password operation is denied.
Is it possible to change the password on behalf of a user? I found conflicting information on this topic on the internet. If this is impossible, what is the valid approach to do this?
I have a SPA frontend app in which the user is authenticated with redirection flow. The access token is then passed to my backend to authorize the requests. Maybe I can use this token to somehow access MS Graph API and change the password?
Note: I would like to let users change their passwords without leaving my SPA application.
I tried in my environment and got below results:
Initially I tried with your code and got same error:
According to MS-DOCS change password we need Directory.AccessAsUser.All permission and it only supported for delegated (Work or school accounts).
Trying to reset the password in the B2C tenant using the Graph API its is not possible Unfortunately, because there is no Directory.AccessAsUser.All, B2C tenant does not allow this type of password reset. For B2C tenants, the Graph API includes the permission. Only offline access and openID are available as delegated rights in the B2C tenant.
You can reset the password in B2C tenant are either admin performing password reset via Azure Portal or by using Password Reset Policy and also refer this MS-Q&A for updating password in powershell and postman.
Reference:
"Upn from claims with value null is not a valid upn." - Microsoft Q&A by amanpreetsingh-msft.

"AADSTS65001: The user or administrator has not consented to use the application" but the Admin has consented

I am adapting the project sample provided by Microsoft for Multi-tenant Azure AD apps.
I am extending SurveyAuthenticationEvents.TokenValidated() so that in the sign up logic, I hit up Microsoft Graph to get the tenant display name so we can store something a little more meaningful than just a GUID to identify the new tenant.
Something like this:
Organization? org = default;
var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>();
var auth = await tokenAcquisition.GetAuthenticationResultForUserAsync(new string[] { "User.Read" }, tenantId: azureTenantId, user: context.Principal); // "User.Read", "Organization.Read.All"
var graphClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
(requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", auth.AccessToken); // context.SecurityToken.RawData);
return Task.CompletedTask;
}));
var results = await graphClient.Organization.Request().Select(x =>x.DisplayName).GetAsync();
org = results.FirstOrDefault();
The third line is failing with the exception:
Microsoft.Identity.Client.MsalUiRequiredException: AADSTS65001: The user or administrator has not consented to use the application with ID 'xxxxxx' named 'xxxxx'. Send an interactive authorization request for this user and resource.
Please note that this is IMMEDIATELY after the tenant administrator has just consented.
However, the error seems to be intermittent. In fact if I debug and break on the problematic line, wait a couple of seconds and then let it run it works fine. It is as if Azure AD needs a second or two after the consent to properly update the service principals and consent status for the new tenant, before it will issue an access token for a downstream API.
Am I missing something here or do I just add some retries and work around the issue?
If an admin consent is already believed to be done , maybe all of the required permissions listed in the sign-in request were not consented to
or
the wrong application was used based on the App-Id}from the table above.
In that case try to add this as an authorized client application
Once the application has been consented ,please make sure the prompt parameter is not being specified. If prompt parameter is still passed after consent this error might occur
For workaround delete the package , permissions and again add it so your permission request gets created again.Also check if you need additional permissions like openid , profile ,offline_access for refresh token in your case.
Please check other possible causes here
Troubleshooting consent in Azure AD | Azure Active Directory Developer Support Team (aaddevsup.xyz) which can guide to troubleshoot
Reference:
Unexpected consent prompt when signing in to an application - Microsoft Entra | Microsoft Docs
Based on some feedback on github (https://github.com/mspnp/multitenant-saas-guidance/issues/127) it appears that the issue is indeed due to timing issues with AzureAD infrastructure, possibly related to caching.
Would be fantastic if this was documented!
I have now introduced some retry logic that simply waits a few seconds and retries the same request (up to 5 times) and the sign up logic now works as expected.
Thanks to #dmcsweeney on github

I need to connect to Azure Media Services with user authentication

I'm writing a commandline tool to manipulate assets in Azure Media Services using the v3 AMS API. It should authenticate using the logged on user. As the Windows AD and Azure AD are synchronised, it should not need to pop up a login dialog box.
This document:
https://learn.microsoft.com/en-us/azure/media-services/latest/access-api-howto?tabs=portal
states that it's possible to use either user or service principal authentication to connect to AMS.
In this document:
https://learn.microsoft.com/en-us/azure/media-services/latest/configure-connect-dotnet-howto
there's an example of how to do service principal authentication but I can't find anything about user authentication. The code in the sample looks something like this:
var clientCredential = new ClientCredential(config.AadClientId, config.AadSecret);
var credentials = await ApplicationTokenProvider.LoginSilentAsync(config.AadTenantId, clientCredential, ActiveDirectoryServiceSettings.Azure);
var amsClient = new AzureMediaServicesClient(config.ArmEndpoint, credentials)
Note that all constructors of AzureMediaServicesClient take a ServiceClientCredentials object, so how can I authenticate using UserCredentials?
Azure Media Services Explorer does user based authentication (and SP auth). https://aka.ms/amse
Code for the user based authentication :
https://github.com/Azure/Azure-Media-Services-Explorer/blob/master/AMSExplorer/Program.cs#L779-L843

Need Help on ROPC flow with Azure AD B2c Custom Policies

we are trying to implement ROPC flow in Azure AD B2C.
I have gone through the B2C Advanced policies and the instructions provided as per below links to configure with B2C Custom Policies and facing some issues.
https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/tree/master/scenarios/source/aadb2c-ief-ropc
https://github.com/Azure-Samples/active-directory-b2c-advanced-policies/blob/master/B2CROPC/yourtenant.onmicrosoft.com_B2C_1A_ResourceOwnerv2%20SINGLE%20FILE%20-%20Copy.xml
Though we have provided correct username and password, we are getting
{
"error": "access_denied",
"error_description": "AADB2C90225: The username or password provided in the request are invalid.\r\nCorrelation ID:
8c15d7ab-ba5b-4baf-be5a-8bfdb9939164\r\nTimestamp: 2019-01-23
06:18:19Z\r\n" }
I could resolve this problem. In my case, I followed this link:
https://learn.microsoft.com/en-us/azure/active-directory-b2c/ropc-custom
But had the same error message.
In step 4 I had to add values for "client_id" and "resource_id". I used the values that I had in another profile ("login-NonInteractive").
And the flow worked successfully.
Have you registered your ProxyIdentityExperienceFramework application as Native?
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-get-started-custom
Registering the ProxyIdentityExperienceFramework application as WebApp/WebAPI might result in this error.

Azure AD OpenIDConnect + ASP.NET Core - Authenticate and Extra Permissions/Token?

I am using the following bits against my Azure AD to authenticate with ASP.NET Core.
https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-webapp-openidconnect-aspnetcore/
https://github.com/Azure-Samples/active-directory-dotnet-webapp-openidconnect-aspnetcore
I have the basic login/auth working after creating an Azure AD app. User can login/logout.
My question is given this, what's the best way when a user Auth's to log to a DB? I thought about making the redirect URL to an endpoint, saving, then just redirecting back to "Home" but is that ideal?
Also, is it possible to retrieve a bearer token via this approach? Or does this require another type of call or extending "scope"? So that for example I could retrieve the authenticated users Manager.
https://graph.microsoft.com/v1.0/me/manager
My question is given this, what's the best way when a user Auth's to log to a DB? I thought about making the redirect URL to an endpoint, saving, then just redirecting back to "Home" but is that ideal?
This way only able to log those who already sign-in your app successfully. It is not able to log those users who are attempt to sign-in your app but enter the wrong password.
Azure AD already provide lots of report to gain visibility into the integrity and security of your organization’s directory.( refer here)
And if you are using the Azure AD Premium, you can review the sign-in activities via the Azure new portal below:
And if you want to store the sign-in activity in your web app, you can write the custom code after the token is verified. Here is the code for your reference:
// Configure the OWIN pipeline to use OpenID Connect auth.
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
ClientId = Configuration["AzureAD:ClientId"],
Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAd:Tenant"]),
ResponseType = OpenIdConnectResponseType.IdToken,
PostLogoutRedirectUri = Configuration["AzureAd:PostLogoutRedirectUri"],
Events = new OpenIdConnectEvents
{
OnRemoteFailure = OnAuthenticationFailed,
OnTokenValidated = context => {
//write the custom code to store users login-in
return Task.FromResult(0); }
},
});
Also, is it possible to retrieve a bearer token via this approach?
Yes. We can get the token after receive the authorization code. You can refer the code sample here to acquire the token from asp.net core app.

Resources