Owin OpenIdConnect Active Directory HttpContext.GetOwinContext doesn't open microsoftonlin login page - active-directory

I'm trying to use Owin and OpenIdConnect to authenticate users via active directory (office 365 online). I've followed this example and I managed to create a new MVC test project and get it all working. (Settings for AD app id, tenant, Web config etc all fine).
I'm now trying to add that functionality into my existing ASP.net mvc application and I can't get the dang thing to work.
This is what I have: An Account Controller with a "void" action like this (from the example that works in my PoC but not in my actual application):
public void SignIn()
{
// Send an OpenID Connect sign-in request.
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" }, OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
When this action is invoked, I expect the browser to be directed to: login.microsoftonline.com..., but instead it opens this page: https://localhost:44301/Account/Login?ReturnUrl=%2fAccount%2fSignIn
It's like it's calling some sort of redirect somewhere and I can't see where.
Help!

I found the answer. I had to do 2 things:
Remove the WebMatrix dll's from the references (apparently nuget package for mvc put it there, so it might come back)
Remove authentication mode="Forms" from web.config
Thanks.

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/

How to redirect on backend for Angular application using Itfoxtec to access app through Azure Active Directory

I am new to using ITfoxtec for Azure Active Directory SAML logins. I read the StackOverflow entry for Nuget ITfoxtec SAML & Angular (and other similar entries for CORS issues), but I still do not understand how to adapt the GitHub Angular example from https://github.com/ITfoxtec/ITfoxtec.Identity.Saml2 to my needs. When running the ITfoxtec GitHub example, the Login method of the AuthController.cs file is immediately executed when I launch the test Angular application, and brings up the Azure Active Directory login prompt.
For my application, I need to click a "Login using Azure Active Directory" button on the Angular front end to call a backend method that can then redirect to another method to attempt login.
.NetCore C# code:
SSOController.cs file:
// This method is called by an Angular front end button when the user wishes to log in via Azure Active Directory SSO
[AllowAnonymous]
[Route("AzureAuth")]
[HttpGet]
public IActionResult AzureAuth(string returnUrl = null)
{
var binding = new Saml2RedirectBinding();
Saml2Configuration config = GetSamlConfig();
binding.SetRelayStateQuery(new Dictionary<string, string> { { relayStateReturnUrl, returnUrl ?? Url.Content("https://localhost:44397/api/sso/AssertionConsumerService") } });
//return binding.Bind(new Saml2AuthnRequest(config)).ToActionResult();
// This gives a CORS error, so we have do ensure that we do the redirection at the backend
// so we try redirecting with "RedirectToAction"
return RedirectToAction("https://localhost:44397/api/sso/AssertionConsumerService");
}
My AssertionConsumerService() method (located in Dev at "https://localhost:44397/api/sso/AssertionConsumerService"), which I need to be redirected to:
[Route("AssertionConsumerService")]
[HttpPost]
public async Task<IActionResult> AssertionConsumerService(HttpRequestMessage request)
{
// After user enters AAD SSO information, redirect should point to here.
// This API endpoint is hit if I test from Azure Enterprise Application SSO testing with the redirect API set to this method.
// I do not understand how to do backend redirects from AzureAuth() method to this method, and ensure that the HTTP request data is correct.
}
Just a follow up to my own question. For logging in directly from the Angular front end, I am having success with using "#azure/msal-angular". Once the end user clicks the "Log in with Azure Active Directory" button and is authenticated back to the frontend, I forward the authentication details to the backend for authorization checks.
I am still using ITfoxtec at the backend to process what can be directly sent from the "Azure Enterprise Applications > Set up single sign on > Test single sign-on with ..." for testing purposes. With the Azure "App registrations > Authentication > Platform Configuration" set to "Single-Page Application", I am making good progress in development and testing.
Sounds like you got a solution.
You can load the Angular application before login if it is hosted a place in the ASP.NET application that do not require the user to be authenticated. Then you can start the login process your selv and validate if the user is authenticated.

Azure Active Directory - UI > API - 401 Error

Good Day,
Currently I have a single tenent with a React UI and .NET Core Apis secured by Azure Active Directory without any problems.
We have recently moved to a new Azure Tenent, new Active Directory etc. I have create two new App Registrations, one single App Service for UI and one for API. I have linked the App Service to AAD (UI = UI App Registration, API = API App Registration).
The problem is the API is getting a 401 error and I think see that in the original tenent the Bearer token is in a JWT format but in the new instance it's not, I believe it my be a graph api access key.
New Tenent:
Authorization: Bearer PAQABAAAAAAD--DLA3VO7QrddgJg7WevrQvEQVbZEMD8su-tIp9k2bTFUTort7SZgeDI52P6KRYefHgtmj4YrecgUKZJ2wylGuhvIzIz642n7Sg0VMU1RwKtrzWlaMqK62CaSoJcstxiEf6 *****
Orginal Tenent:
Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiI3OThkN2ZkOC0zODk2LTQxOGMtOTQ0Ny0wNGFlNTQ2OGFkNDIiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83ZDE3NTU3Ni03Y2Y3LTQyMDctOTA5My0wNmNiNmQyZDIwNjAvIiwiaWF0IjoxNjE2NDUyNzExLCJuYmYiOjE2MTY0NTI3MTEsImV4cCI6MTYxNjQ1NjYxMSwiYWNyIjoiMSIsImFpbyI6IkFTUUEyLzhUQUFBQU9mejhPZHp *****
Please someone kindly enought to provide some guidance / input where I am going wrong.
Regards
Paul.
When using Azure AD to obtain an access token, an additional resource parameter is required. Otherwise, the access token is not a JWT.
For example, if your web API's application ID URI is https://contoso.com/api and the scope name is Employees.Read.All, then with oidc-client the client configuration should be :
scope: 'openid profile email Employees.Read.All',
extraQueryParams: {
resource: 'https://contoso.com/api'
}
In App Service auth configuration, you can use additionalLoginParams
"additionalLoginParams": ["response_type=code", "resource=https://contoso.com/api"]
If you did not use a custom application ID URI, it may look like
api://868662dd-3e28-4c7f-b7d5-7ec02ac9c601
Quickstart: Configure an application to expose a web API
Firstly, the scope is incorrect.
You should Expose an API in your API App Registration and then add it as a permission in your UI App Registration. You can refer to this document.
And when you try to call the 'https://login.windows.net/{tenant}/oauth2/authorize endpoint, you need to specify the scope to include api://{app id of the API App Registration}. For example: api://{app id of the API App Registration} openid profile email. Then the access token would be for calling your API.
At last, for CORS issue, please configure the CORS as * in your web app to see if it helps.
Try to follow this step: Configure App Service to return a usable access token
In my experience, this problem occurs, when you try to authorize against version 1 of the endpoint.
Instead of calling
https://login.microsoftonline.com/{tenant}/oauth2/authorize
call
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
You might be required to set something like "metadata URL" in you authorization library to:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/.well-known/openid-configuration
Make sure your builder follows this order...lifted from our API program.cs
These must be in order of
UseRouting -> UseAuthentication -> UseAuthorisation -> MapControllers
> app.UseRouting()
> app.UseAuthentication()
> app.UseAuthorization()
> app.MapControllers()
If app.UseAuthentication and app.UseAuthorization are not in this order in statement position you Will get 401 Unauthorised as at 01/2023 .Net 6 Core.

Connecting Blazor Wasm to Identity Server 4 - Register and account management links not working

Hopefully someone can guide me in the right direction, because I've been working on this for a while now.
I've create a Blazor WASM hosted in .Net Core. However instead of using the identity in the Server (API) project, I wanted to use for authentication an Identity Server hosted in a different project (so that I can use a standalone Identity Server).
I've create an Identity Server 4 project and also scaffold-ed the Identity Razor pages (so that I have the full flow with registration, account management, password recovery etc.) instead of the basic 3 or so pages that Identity Server generates.
In my Blazor Client project I've added the following inside the Main method:
{
// Bind to the oidc section in the appsettings.
builder.Configuration.Bind("oidc", options.ProviderOptions);
options.UserOptions.RoleClaim = JwtClaimTypes.Role;
})
Also, in my appsettings file I have the following oidc section:
"oidc": {
"Authority": "https://localhost:5001",
"ClientId": "ProjectAllocation.Client",
"DefaultScopes": [
"openid",
"profile",
"roles",
"offline_access"
],
"PostLogoutRedirectUri": "/",
"ResponseType": "code"
}
}
In Identity Server, in the Startup ConfigureServices I am redirecting the Login \ Logout to use the pages in the scaffolded Identity Area:
var builder = services.AddIdentityServer(options =>
{
...
options.UserInteraction.LoginUrl = "/Identity/Account/Login";
options.UserInteraction.LogoutUrl = "/Identity/Account/Logout";
options.Authentication = new IdentityServer4.Configuration.AuthenticationOptions
{
CookieLifetime = TimeSpan.FromHours(10), // ID server cookie timeout set to 10 hours
CookieSlidingExpiration = true
};
})
Now the login and logout work and it seems I am getting the right token data in the client; I haven't implemented the API on the server side yet.
My problem is that the register and the account management links from the Client project are not working. If you would use the template from the VS with integrated identity server then you would be able to click on the register link inside the client app and be taken to the Account\Register page in the Identity area; also once you logged in you can click on the "Hello ...." link and be taken to the Account management in the Identity area.
However this doesn't work in my case. If I navigate from the browser directly to those areas then it works (i.e.: browse to https://localhost:5001/Identity/Account/Register: it works).
When I click on Register button in the Client app it just reloads the app with the following link:
https://localhost:44395/?returnUrl=%2Fauthentication%2Flogin : it looks as if the app is being asked to login, even though the Register page in the Identity Server is marked to allow anonymous access.
I am really puzzled as to why this doesn't work. I can't figure out which settings in the Blazor project sets the links to navigate to via the RemoteAuthenticatorView. I am considering replacing the register button so that it doesn't navigate via the RemoteAuthenticatorView anymore and instead it uses a regular link directly to the Identity Server Register page, but I am not sure what the implications are; also it's really annoying that I cannot get this to work properly.
I've even tried to change the path to the register page so that instead of Identity/Account/Register is Account/Register via the ConfigureServices in the Startup file in the Identity Server 4:
services.AddRazorPages(options => {
options.Conventions.AddAreaPageRoute("Identity", "/Account/Register", "Account/Register");
});
which works from the browser (https://localhost:5001/Account/Register), but it still didn't work from the WASM Blazor Client.
Any ideas?
Thanks,
Raz
I am leaving this here in case someone else stumbles upon this.
I've looked through the Blazor WASM code and for registration and account management it uses the NavigationManager to navigate to the paths supplied in RemoteRegisterPath and RemoteProfilePath properties of the AuthenticationPaths.
For some strange reason though it looks like you cannot navigate to an outside url: the NavigationManager will ignore the supplied base address and use the base address of the project. So even though I've tried to provide an address like https://localhost:5001/Identity/Account/Register, the application actually navigates to https://localhost:44395/Identity/Account/Register.
As a workaround I've created a controller called Account with two methods Register and Manage which will redirect to the address of the Identity Server. So the Blazor client will call the corresponding method in the Account controller in the Blazor API server project which will redirect to the corresponding Identity Server page.
I've modified the call to AddOidcAuthentication() in the Main method inside the Blazor Client project:
builder.Services.AddOidcAuthentication(options =>
{
// Bind to the oidc section in the appsettings.
builder.Configuration.Bind("oidc", options.ProviderOptions);
options.AuthenticationPaths.RemoteRegisterPath = "Account/Register";
options.AuthenticationPaths.RemoteProfilePath = "Account/Manage";
options.UserOptions.RoleClaim = JwtClaimTypes.Role;
})
I've also created an AccountController in the Controllers folder in the Blazor API server project:
[Route("[controller]")]
[ApiController]
public class AccountController : ControllerBase
{
[AllowAnonymous]
[HttpGet("Register")]
public IActionResult Register(string returnUrl)
{
return Redirect(#"https://localhost:5001/Identity/Account/Register?returnUrl=https://localhost:44395/" + returnUrl);
}
[AllowAnonymous]
[HttpGet("Manage")]
public IActionResult Manage(string returnUrl)
{
return Redirect(#"https://localhost:5001/Identity/Account/Manage?returnUrl=https://localhost:44395/" + returnUrl);
}
}
Might be a good idea to authorize the Manage method. Also the returnUrl would probably need some additional parameters (at least for the login \ logout there are more parameters).
In addition, I needed to make some small changes in the Identity files scaffolded in the Identity Server project to allow redirection to non-local paths.
There are certain things that can be improved and it does feel like a hack, but the solution works for now and I couldn't find any better alternatives.
The standard IdentityServer4 project templates does not include any pages for registering users, these page you have to develop your self inside IdentityServer4. To get user registration pages you can try one of these projects/products:
An ASP.NET Core IdentityServer4 Identity Template with Bootstrap 4 and Localization
AdminUI

Drupal 7 SSO via simplesaml_auth module

Currently developing a SSO method for my Drupal website. I've installed simplesamlphp successfully and also configured it. I have also installed the simplesaml_auth module on my website and the SSO procedure works fine. The only problem I am having is when a user logs in via the SSO method I need to redirect them to a certain page when login is successful and I am not sure where to edit the code to be able to do this.
Any help is welcome.
Thanks!
You can add redirect condition wise in below function of simplesaml auth module
simplesamlphp_auth_loginpage() {
change drupal_goto path here to set new redirect.
}
Add a destination menu item id query parameter in the SAML login url to which it should b redirected after successful login.
Generally the SAML menu item is saml_login which makes the SAML login url like https://[SITE_NAME]/saml_login now just add it a destination query parameter like https://[SITE_NAME]/saml_login/?destination=after_login
Where after_login should be a custom menu_item defined in any of the custom module containing the callback function for redirection.
If needed any existing menu item of core or contributed module can be also used in the destination.

Resources