I have configured my Web application to use Azure Auth logon. Everything works fine and users can logon if they're not already logged on to Azure.
My issue is that when a user is already logged into Azure of Office 365 and they browse to my site, they get this error below. I understand what the error means, but I want to know if there is a way to redirect to another URL (on my site) if this issue occurs. Here is that error:
This is my startup code for configuring OpenId Auth:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions {
ClientId = Configuration.clientID,
Authority = authenticationAuthority,
PostLogoutRedirectUri = Configuration.logoutRedirectURL,
Notifications = new OpenIdConnectAuthenticationNotifications {
AuthenticationFailed = context => {
context.HandleResponse();
context.Response.Redirect("/Unauthorised.aspx?message=" + context.Exception.Message);
return Task.FromResult(0);
}
}
});
There are a couple of ways around this, depending on your scenario.
If you want to authenticate them using their existing credentials, you can enable multi-tenant support in your application's registration. This will allow an external user to authenticate with your application using their own AAD credentials rather than one in your AAD tenant.
If you need to force them to reauthenticate using your credentials, you can add prompt=login to your initial Authorization URI (https://login.microsoft.com/{tenant}/oauth/authorize?...&prompt=login). This will force the user to authenticate against your application, even if they already have an active authentication cookie (in most cases "authenticate" here simply means that the user will need to select an account from a list, not re-enter id & password).
Related
I am using Microsoft.Identity.Claim library to conenct to azure and authenticate user.
My first idea was to use AcquireTokenByIntegratedWindowsAuth method but that requires few days until network administrator people investigate how to enable single sign-in option and change that user are now "federated" and not "managed. So I now switched to AcquireTokenInteractive method because chances are that ure will be logged in, so he will just need to choose account from automatically opened browser and that's it. No big deal.
And this works:
string clientId = "xxx";
var tenantId = "yyy";
string[] scopes = new string[] { "User.Read", "User.ReadBasic.All"};
AuthenticationResult result;
var app = PublicClientApplicationBuilder.Create(clientId)
.WithRedirectUri("http://localhost")
.WithAuthority(AzureCloudInstance.AzurePublic, tenantId).Build();
try
{
result = await app.AcquireTokenInteractive(scopes)
.ExecuteAsync();
}
catch (MsalUiRequiredException) //see all possibl exceptions!
{
However, I don't receive claims inside token.
My idea is to send this token to server, then validate it, and if sucessfull create user in database and then use my own authenication mechanism I use for other users (that are not part of domain, completely separate user).
But I don't want all users from domain have access to this app.
So I would like to get claims, roles...
How to get claims, using this or any other lib given user email, or some other unique data?
Here I summarize all of the steps you may need to follow:
1. You need to register a app in azure ad for your service app, you can refer to this document
2. Then you need to register another app in ad as the client app, you can follow the steps in this document
3. After that, you need to do the steps in this document which I already provided in comments. Do it in the service app but not client app.
4. Then you can get the access token with your code and check the claim roles. Please note, do not add microsoft graph permissions into scopes in your code. You need to add api://<the client id of the registered app for service app>/.default into scopes.
5. Now you can find the claim roles in your access token.
I am using Azure AD app to app authentication and also user authentication.
Now, from within the same AD tenant any registered app is able to call my app with both user or app token even though I have not added/white-listed the caller app. This is in contrast to what use to happen couple of years back where we had to add delegated permission in our app registration permissions to allow any app to call us with a token.
My Asp.Net Core App is using below code snippet to setup authentication.
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer((option) =>
{
option.Audience = audience;
option.Authority = authority;
option.TokenValidationParameters = new TokenValidationParameters()
{
ValidateAudience = true,
};
});
Please let me know why there is no need to add delegated permission in Azure AD app anymore?
You may have hit one of the features of Azure AD.
An app in any tenant can acquire an access token for an API in any tenant as long as they know its identifiers (tenant id + client id/app id URI).
The token will not contain any delegated permissions or application permissions, there is no way for it to get those without requiring them + someone consenting them of course.
But it will be otherwise valid.
You need to check in your API that the caller has appropriate permissions to call your API.
Check that the token contains a valid delegated permission or application permission.
Delegated permissions will be space-delimited in the scp claim, and application permissions will be in an array in the roles claim.
Failing to do these checks can leave your API vulnerable.
I'm trying to establish whether it's possible to make use of various authentication mechanisms in our web API. The two we are looking at is:
Auth against db using username and password (current implementation)
Auth against Azure AD
The thing I'm struggling to get my head around is:
How do I configure both. In other words, know which mechanisms to use in the API
Secondly, how do I make use of a different ida:ClientId (Azure AD Auth) during run-time (multi tenant site)
Many thanks in advance!
We can add multiple authentication middleware directly in the web API project. To add the authentication using Azure AD, we can use Microsoft.Owin.Security.ActiveDirectory. And here is the code support both for the individual and Azure AD account for your reference:
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
});
}
To authenticate the local account, we can get the access token from the authorization server build with web API project. And for the Azure AD account, we need to get the token from Azure AD.
How do I configure both. In other words, know which mechanisms to use in the API
In the front-end application, you should also provide a button to login with Azure AD then acquire the access token from Azure AD. Then you can call the web API using this access token as the individual accounts.
Secondly, how do I make use of a different ida:ClientId (Azure AD Auth) during run-time (multi tenant site)
If you want to develop a multi tenant site, when you register the web app/API app on Azure AD, we need to enable the Multi-tenanted. And replace the tenant in the authorization/token endpoint with common. After that, the users from other tenants could login-in your app. More detail about multi-tenant development, you can refer link below:
How to sign in any Azure Active Directory (AD) user using the multi-tenant application pattern
I am using OpenID Connect to connect to Azure ID, I can successfully authenticate in Azure and get the request coming back to the redirect uri specified in OpenID Azure AD Configuration.
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
AuthenticationType = " TEST",
Caption = "Test Azure AD",
SignInAsAuthenticationType = signInAsType,
ClientId = "<client ID>",
Authority = "https://sts.windows.net/<tenantId>",
ResponseType = OpenIdConnectResponseTypes.CodeIdToken,
RedirectUri = "https://localhost:44392/External/Login", This is another webapi project, not identityserver host.
AuthenticationMode = AuthenticationMode.Passive,
});
After succesful authentication it is redirecting back to https://localhost:44392/External/Login with Code, IdToken.
Questions :
Does it not stop at AuthenticateExternalAsync method on redirection unlike google-signin ?
Do i have to decode IdToken JWT to get user claims?
In the redirection method, how do i generate Access Token from IdSrv3 to authorize other webapis ?
Can a user have both Local Login and Multiple External logins ( Azure AD, Google etc ). In this case how does SSO works with IDsrv3 ?
Is there any IdSrv3 sample with External logins implemented ? Preferably Azure AD ?
I've just struggled through this process, so I'll attempt to answer as best I can to help you/others. Forgive me if I misunderstand your question.
AuthenticateExternalAsync should be called, but you need to have AzureAd return to the IDS (Identity Server) rather than to your App. Your flow should look something like: app -> IDS -> AzureAd -> IDS (AuthenticateExternalAsync) -> App.
In AuthenticateExternalAsync you get the ExternalAuthenticationContext.ExternalIdentity, which contains the claims - no need to decode the JWT token.
IDS handles this once you return a successful AuthenticatedResult in AuthenticateExternalAsync, something like context.AuthenticateResult = new AuthenticateResult("UserId", name, claims);
Yes. You can force the method of logging in as described for SSO purposes, otherwise I imagine IDS would handle it post first-login.
I found this helpful (runs through setup of IDS and AzureAd), but it does use the old Azure Portal rather than the new one. They don't seem to have any samples in their gallery.
Hope that helps a bit :)
I am using MSAL to connect my Xamarin.Forms-Windows 8.1-App to Azure AD B2C with a custom SignInSignUp-policy (to login the user by using a custom E-Mail address and a password). The "normal" authentication against Azure AD (without custom policy) works fine, but when I use the policy, the message "We can't connect to the service you need right now. Check your network connection or try this again later." appears everytime after providing the credentials (directly within the dialog). Since the dialog does not finish correctly, I am not retrieving any exception or AuthenticationResult and so I am not able to determine the concrete issue (the internet connection itself is not the problem).
Note: I also tried this in a Xamarin.Forms-UWP-App which leads me to the same issue. Under iOS, it is working fine and the dialog finishes and closes correctly.
NuGet Versions:
MSAL (Microsoft.Identity.Client): 1.0.304142201-alpha
Xamarin.Forms: 2.3.2.118-pre1
Thats my code (simplified):
var clientId = "{My application's ClientId}";
var redirectUri = "urn:ietf:wg:oauth:2.0:oob";
var authority = "https://login.microsoftonline.com/{My Azure AD B2C}";
string[] scopes = { clientId };
var policy = "{My SignUpSignIn policy}";
var clientApplication = new PublicClientApplication (authority, clientId);
clientApplication.RedirectUri = redirectUri;
var result = await this.clientApplication.AcquireTokenAsync(scopes, string.Empty, UiOptions.SelectAccount, string.Empty, null, authority, policy);
Any ideas on this?
Thanks in advance!
Regards,
Marcel
I had the same issue. Turns out I forgot to properly set up my mobile app to allow loggin in via Active Directory
The steps I took that solved my problem were:
In Azure B2C Blade select Application and set the Reply URL to the address of the Azure Mobile Apps instance (e.g. https://myapp.azurewebsites.net), followed by /.auth/login/aad/callback
Make sure the policies used in the Azure Active Directory B2C tenant should be configured so that the Reply URL is set to the same as above
In the Azure Mobile or Services App go to settings-->authentication/autorization and make sure that a non authenticated request is set up to log in with AAD
in the same blade select the AAD provider, go to advanced and set up Client ID and Issuer URL, with the Client ID being the Application ID of the Azure Active Directory B2C tenant, and the Issuer Url being the Metadata Endpoint for the Azure Active Directory B2C policy
Once I did the above all worked flawlessly.
More detailed instructions can be found at https://developer.xamarin.com/guides/xamarin-forms/web-services/authentication/azure-ad-b2c-mobile-app/
Let me know if this helped...