Multiple open id connect ad providers in a CMS setup - azure-active-directory

The case
Currently trying to setup two AD providers (both on OpenID Connect (OIDC) protocol).
One would need to handle users for the back office and the other should be used in all other cases to login external users with different roles. Content on the website is only accessible for certain roles.
The setup
EPiServer (CMS)
.Net 4.7.2 framework
Important notes:
Both open id connect middlewares are currently set to authentication mode 'active' .
Status
Both AD providers can be challenged directly where the right login portal shows, however there are some problems i cannot explain. Working with two open id connect middelwares is a first for me.
Problem 1
In a CMS setup certain location/paths are defined in the web.config like the following
<location path="episerver">
<system.web>
<authorization>
<allow roles="WebEditors, WebAdmins, Administrators" />
<deny users="*" />
</authorization>
</system.web>
When the '/episerver' path is hit it triggers an authentication flow. If one middleware has been marked to run in the pipeline stage 'authentication' that middleware seems to always handle such requests, however if both middleware are registered to run in same pipeline stage 'authentication' the last registered middleware (in the owin startup file) always seems to handle all requests. Why is that ?
Problem 2
When the first middleware is registered to run for the authentication pipeline stage, and the second is registered to run for a later pipeline stage (the default seems to be 'PreRequestHandlerExecute' when its not specified) another strange behaviour happens.
When any controller that has a '[Authorize]' attribute assigned is hit with a request, my guess would be the first middleware would be challenged because it is the first 'active' middleware defined in the Owin pipeline, however it is the second middleware that is hit. I can't find any explaination on this strange behaviour ?

You need to configure the back-office azure ad config to only trigger on /episerver and the regular users on everything else in startup.cs
Both can use the same cookie auth setup but will need 2 instances of OpenIdConnectAuthenticationOptions, one for each azure ad.
So you can do like this:
app.MapWhen(!ctx.Request.Path.StartsWith("/episerver"), cmsApp =>
{
cmsApp.UseOpenIdConnectAuthentication(cmsOptions);
}
app.Map("/episerver", editorApp =>
{
editorApp.UseOpenIdConnectAuthentication(editorOptions);
}

Related

Blazor WASM with Azure AD SSO

I have a Blazor WASM client and a Web API with working Azure AD authentication and authorization but the users always have to push the button to log in. I want to use SSO for make them easy this process. I tried to find on Internet how I can put this feature in the application but no success. Can someone to show the right direction, please?
I do not insert source code because those who are experienced in this will know what it is about. Thx
• Yes, you can configure SSO in Blazor WASM app very easily by following the below said procedure as shown. Also, you need to determine the authentication method for the Blazor WASM app, i.e., SAML, OAuth 2.0, OpenID as such. Therefore, I am considering SAML as the authentication mechanism in here.
To facilitate the SAML SSO authentication through Azure AD, you will have to install packages related to it in your .NET Core product from its official website. Here, we are using ‘ComponentSpace.SAML.2.0’ package using the NuGet Manager. Once the installation is complete, we need to inject the service of ‘ComponentSpace’ in our project by adding service and cookies in the ‘Program.cs’ file whose code looks like this: -
builder.Services.Configure<CookiePolicyOptions>(options =>
{
// SameSiteMode.None is required to support SAML SSO.
options.MinimumSameSitePolicy = SameSiteMode.None;
});
builder.Services.ConfigureApplicationCookie(options =>
{
// Use a unique identity cookie name rather than sharing the cookie across applications in the domain.
options.Cookie.Name = “StudentPortal.Identity”;
// SameSiteMode.None is required to support SAML logout.
options.Cookie.SameSite = SameSiteMode.None;
});
// Add SAML SSO services.
builder.Services.AddSaml(builder.Configuration.GetSection(“SAML”));
Once done, we can modify the ‘appsettings.json’ file to add to the ‘ComponentSpace’ settings. There are many parts which we can add in the ‘appsettings.json’ file,i.e., ‘schema’, ‘LocalServiceProviderConfiguration’, ‘PartnerIdentityProviderConfigurations’, ‘SingleSignOnServiceUrl’, ‘SingleLogoutServiceUrl’ and ‘ArtifactResolutionServiceUrl’ refers to the IDP server side’s service URL wherein it should be your Azure Cloud’s URL and these URLs are where our applications send sign-on and logout requests which also includes the ‘PartnerName’, i.e., IDP’s name and URL.
To do so, you will have to include the below in your ‘appsettings.json’ file placed under ‘wwwroot’ folder: -
{
"oidc": {
"Authority": "< insert the SSO provider URL here >",
"ClientId": "< unique client id as specified in the SSO provider >",
"ResponseType": "code",
"DefaultScopes": [
"openid",
"profile"
],
"PostLogoutRedirectUri": "authentication/logout-callback",
"RedirectUri": "authentication/login-callback"
}
}
Thus, once done, we will add a new file to the same folder by the name of ‘LoginDisplay.razor’ which is displayed as follows: -
#using Microsoft.AspNetCore.Components.Authorization
#using Microsoft.AspNetCore.Components.WebAssembly.Authentication
#inject NavigationManager Navigation
#inject SignOutSessionStateManager SignOutManager
<AuthorizeView>
<Authorized>
<button class="nav-link btn btn-link" #onclick="BeginSignOut">Log out</button>
</Authorized>
<NotAuthorized>
Register
Log in
</NotAuthorized>
</AuthorizeView>
#code{
private async Task BeginSignOut(MouseEventArgs args)
{
await SignOutManager.SetSignOutState();
Navigation.NavigateTo("authentication/logout");
}
}
Thus, as all the configurations required are done as given above, the program will call ‘SAML/InitiateSingleSignOn’ function and send an SSO sign-in request to IDP, and now our program automatically run into the ‘SAML/AssertionConsumerService’ function and start to wait for IDP's reply, after receiving the response from the IDP. Please find the below snapshots for your reference while following the above steps: -
Certificate import: -
Adding ‘SAML Service Provider’ as a SAMLController as said: -
Adding ‘ComponentSpace.SAML.2.0’ package as below: -
For more detailed information, kindly refer to the below links: -
https://kevinzheng1989.medium.com/build-the-azure-sso-login-page-in-blazor-server-application-with-saml-b0959a50c0a6
https://scientificprogrammer.net/2022/08/12/single-sign-on-user-authentication-on-blazor-webassembly-signalr-client/

Get error "login.live.com page can’t be found" when invoking Azure Ad as external IDP in IdentitySrever4

I try to follow this tutorial to add Azure Ad as another external IDP for my IdentityServer4 service (I have gotten Windows and Google working already). I can get the "Azure Ad" button displayed on my IdentityServer login page now, but when I click on it, I get the following error returned:
Here is how I configured Azure Ad in ConfigureServices of my Startup class. I also tried replacing "aad" with "oidc", which is what I used and worked in Google, but no difference here.
and here is how my Azure Ad account configuration looks like. The colors match up with above indicating the values I use in my code:
Can someone tell me what I may be doing wrong here?
Initially please try by deleting history in the browser and use "login.microsoftonline.com/<tenantId>/v2.0/" as authority string.
And options.CallbackPath = "/signin-oidc"; options.ResponseType = "code id_token";
NOTE : The identity platform which is used by Microsoft has a character limit for links. This type of error will appear if the authorization request or link is longer than the said limit,.
Protocols like OpenID Connect, allow state as a parameter in the authorization request, and the identity provider will return that state in the response as you can find that in error page you provided .
Because of which the request URL becomes large as sometimes the state parameter is long.(which might be the possible case here)
Try to call the AddOidcStateDataFormatterCache extension method on the IServiceCollection in startup class which uses the distributed cache in the backend like:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers());
services.AddAuthentication()
.AddOpenIdConnect("aad", "Azure AD", options =>
{
// ...
})
you can write the way as below :
services.AddOidcStateDataFormatterCache(); //Add this line
services.AddAuthentication()
.AddOpenIdConnect("aad", "Azure AD", options =>
{
// ...
})
You may check these similar References for more details :
Sign-in with External Identity Providers — IdentityServer4 1.0.0 documentation
(Or)
See section : 22.4 Handling the callback and signing in the user in IdentityServer4 Documentation
At least check for dns or firewall issues .

connect azure function to b2c

So, I created azure b2c directory, and created inside it application like https://github.com/Azure-Samples/active-directory-b2c-javascript-msal-singlepageapp, and I created azure function in general azure directory that suppose to read blob and return json file. Also I created custom login page for sign in.
I ran my program locally, and I can login, and instead of call API that uses in github, I call azure function and it works.
But now I want to secure access to function, so I make authLevel 'user' and try to make Authentication via Azure Active Directory.
And no mater how I make settings, or I can't connect because I don't have permissions, or I can't use function because I don't have permissions.
Also I get this error The client id ’/.auth/login/aad/callback' specified in the request is not registered in tenant ‘’.”
How should I connect function to b2c so only authorised users can have access to function response.
Setting up B2C authentication for your Azure Functions App is actually really easy:
Create Azure Functions App and write down the URL
E.g. https://myazurefunctions.azurewebsites.net (make sure to make it a HTTPS URL)
Configure your application in Azure Active Directory B2C:
Write down the Application ID
Add a reply URL for your Functions App,
adding the suffix /.auth/login/aad/callback. E.g.
http://myazurefunctions.azurewebsites.net/.auth/login/aad/callback
Get the Metadata Endpoint URL for your Sign-in policy
If you open the details of your sign-in policy, you'll find it right at the top. E.g.:
In your Functions App, on the bottom left select "Function app settings" and go to "Configure authentication":
Turn on authentication and select Azure Active Directory:
Select the advanced settings and enter the following values:
Client ID: The Application ID which you copied in step 2. a.
Issuer Url: The Metadata Endpoint URL from step 3.
Save your settings and you're done!
With the new "User flows (policies)" a few small changes must be made to the selected answer:
Perform Step-3 as follows to get the "Metadata Endpoint URL”:
a) Go to your B2C tenant and click on User flows (policies).
b) Select your login (or sign up sign in) flow and click on “Run user flow”.
c) Your "Metadata Endpoint URL” is displayed at the top of the new window – right beneath the ”Run user flow” heading.
Perform Step-4 and 5 as follows to configure “Authentication”:
a) Go to your function apps and click on your function app (NOT on one of your functions inside your function app).
b) Click on Platform features and then on Authentication / Authorization.
c) Turn on “App Service Authentication”. Select “Log in with Azure Active Directory” and then click on “Azure Active Directory – Configured (Advanced)”.
Continue with Step-6.

Azure Active Directory Web Application without login current user

I am following an older tutorial (https://code.msdn.microsoft.com/Write-Sample-App-for-79e55502) that shows how to create a web application that connects to an Azure Active Directory tenant using ADAL. There is a class library that contains DirectoryService classes that I believe does the work in retrieving AD user properties. I am wanting to create a login method for this project for security purposes, and to be able to identify what user is logged in to the application. Currently there is not a signin method that authenticates against AD by entering a username/password, so I am a little puzzled at how the app can retrieve user properties with just the AppId,Domain,and AppSecret in the Web.config without actually having someone login with either their AD creds or redirecting to login.microsoftonline/{tenantId}.....I do not know if I am making sense, but I want to be able to add a login method so a user is forced to login so it gets the claims for that specific user but if I am already using ADAL, can I also incorporate Owin?
There are two parts to your question -
1. How is this app working today, without asking end users to explicitly sign in
This sample is using Client Credential Grant, in which you don't need end users to sign in, but use the identity of an application itself to get the auth token and use it for further operations. As you mention yourself, it just needs AppId, Domain and App Secret from web.config. You can read all about it here - Client Credentials Grant
Related code to acquire token is available in MVCDirectoryGraphSample\Helpers\MVCGraphServiceHelper.cs file
AuthenticationContext authenticationContext = new AuthenticationContext(authString);
ClientCredential clientCred = new ClientCredential(ConfigurationManager.AppSettings["AppPrincipalId"],
2. How to add a login method to force users to sign in to your web application
You can start using something like Authorization Code Grant flow, instead of client credentials. Look here for documentation on different scenarios that Azure AD supports. Your case looks like a web application calling Graph API, described here
Exact code sample to do this is available here - Code Samples

How to configure on-behalf-of authentication in multi-tenant environment?

I have a native client that calls a service I wrote-- that in turn calls the Graph API (using the original caller's credentials).
This is exactly like the 'onbehalfof' sample found here (my code fails the same way as the sample):
https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof
When logging in as a user from the same tenant as the service (tenant A), everything works fine (just like the onbehalf of sample). When logging in as a user from a different tenant (tenant B), I get an exception on this line in the service:
result = await authContext.AcquireTokenAsync(GraphResourceId, clientCred, userAssertion);
(this is line 153 from TodoListController.cs in the onbehalfof sample).
The exception is this:
AADSTS65001: The user or administrator has not consented to use the
application with ID 'de2fb28b-83f8-419d-9b00-3fbce0a60bf4'. Send an
interactive authorization request for this user and resource.\r\nTrace
ID: 6865c420-674a-4adf-a070-3d9b9c500200\r\nCorrelation ID:
7e088563-d7fe-4131-a05c-cbe04dbb2bbd\r\nTimestamp: 2017-03-29
22:56:58Z
The application id above refers to the service I wrote (which is the same line in the TodoListService in the onbehalfofsample).
I configured everything for multi-tenant authentication. But it's the additional call that my service is making to another service (Graph API) that's causing the problem. What additional configuration do I need to do in the Azure portal to make this work?
In the instructions written for the sample you linked above, they address this issue with the following section:
Configure known client applications
For the middle tier web API to be able to call the downstream web API,
the user must grant the middle tier permission to do so in the form of
consent. Because the middle tier has no interactive UI of its own, you
need to explicitly bind the client app registration in Azure AD with
the registration for the web API, which merges the consent required by
both the client & middle tier into a single dialog. You can do so by
adding the "Client ID" of the client app, to the manifest of the web
API in the knownClientApplications property. Here's how:
Navigate to your 'TodoListService' app registration, and open the manifest editor.
In the manifest, locate the knownClientApplications array property, and add the Client ID of your client application as an element.
Your code should look like the following after you're done:
"knownClientApplications": ["94da0930-763f-45c7-8d26-04d5938baab2"]
Save the TodoListService manifest by clicking the "Save" button.
My assumption is that because you are running into this problem, that you have not done this special configuration.
The other option you have is to explicitly request consent between the middle tier and the AAD Graph API. You can do this by having a tenant administrator 'login' and consent to your middle tier service. All you need to do is generate a login url with the middle tier App ID.
However, I strongly recommend you do it the documented way, since this will provide a better experience for your users.
It's working now. I had to make two changes to get it working.
First, on the service side switch to using "common" as the tenant. I had switched to common on the client but didn't realize you had to do this on the service side as well:
<add key="ida:Tenant" value="common" />
Second, change the GraphUserUrl on the service to the following URL:
<add key="ida:GraphUserUrl" value="https://graph.windows.net/me?api-version=1.6" />
The original URL in the sample didn't work (at least for users in another tenant).
Here's the consent dialog that appears when a user from another tenant logs in:
Consent Dialog
Here's my client manifest...
Client Manifest
...and my service manifest...
Service Manifest

Resources