When deploying two applications (one .net 4.6 the other .net core 2.2) that share an authentication cookie to a web farm environment, the "receiving" app does not authenticate. We have a very large web forms application that we are trying to eventually migrate to .net core, so for now we are handling the authentication in the web forms app and trying to share that authentication with the .net core app. We have upgraded the authentication in the web forms app to OWIN/Katana cookie based authentication. The apps are deployed on the same servers under the same site (server.com/app1 server.com/app2). Everything works fine locally, you sign in on one and move to the other and you are still logged in. When we deploy to our servers, which are load balanced, the .net core app receives the cookie, but isAuthenticated is false.
I have been able to manually decrypt the cookie in the .net core app and it is able to print out the claims contained within it, but the IsAuthenticated flag is still false. I've tried changing the cookie domain, cookie path, security policy, and authentication type with no success.
Web Forms app Startup.cs:
var provider = DataProtectionProvider.Create(new DirectoryInfo(System.Configuration.ConfigurationManager.AppSettings["KeyRingLocation"]),
(builder) => {
builder.SetApplicationName("sharedApp");
builder.PersistKeysToFileSystem(new DirectoryInfo(System.Configuration.ConfigurationManager.AppSettings["KeyRingLocation"]));
});
IDataProtector protector = provider.CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware",
"Identity.Application",
"v2");
app.UseCookieAuthentication(new Microsoft.Owin.Security.Cookies.CookieAuthenticationOptions
{
CookieName = ".AspNet.SharedCookie",
LoginPath = new PathString("/Login.aspx"),
CookiePath = "/",
AuthenticationType = "Identity.Application",
CookieSecure = Microsoft.Owin.Security.Cookies.CookieSecureOption.Always,
CookieDomain = System.Configuration.ConfigurationManager.AppSettings["CookieDomain"],
TicketDataFormat = new AspNetTicketDataFormat(new DataProtectorShim(protector)),
CookieManager = new ChunkingCookieManager()
});
.net core app Startup.cs:
services.AddDataProtection()
.SetApplicationName("sharedApp")
.PersistKeysToFileSystem(new DirectoryInfo(Configuration.GetSection("KeyRingLocation").Value));
services.AddAuthentication("Identity.Application")
.AddCookie("Identity.Application", options =>
{
options.Cookie.Name = ".AspNet.SharedCookie";
options.Cookie.Domain = Configuration.GetSection("CookieDomain").Value;
options.Cookie.Path = "/";
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
web forms login code:
...
var auth = Context.GetOwinContext().Authentication;
var identity = new ClaimsIdentity("Identity.Application");
identity.AddClaim(new Claim(ClaimTypes.Name, profile.UserName));
...
auth.SignIn(identity);
There are no errors being thrown so it is really hard to figure out what the issue is. I would expect it to respect the authentication cookie as it does running locally, but the user identity is null and isAuthenticated is false.
Related
To get an overview, I have an old .NET Framework 4.7.2 Website with a lot of .aspx Files and I have a new .NET Core WebApp. Both are running on the same server under the same domain with different ports.
I now want to login into the .NET Core Website and be able to use the Authentication Token on the .NET Framework Website too.
I tried to use the Cookie generated by the .NET Core Website to Authenticate on the .NET Framework Website with Owin, but I couldn't find any way to get this to work.
Does anyone have an Idea on how to accomplish this? I need to authenticate once and be able to stay Authenticated over both websites.
To share authentication cookies between your ASP.NET 4.x applications and your ASP.NET Core applications, firstly, configure the ASP.NET Core application by following the steps:
Add Authentication to your app
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication();
//other services...
}
In your Configure method use the CookieAuthenticationOptions to set up the data protection service for cookies
app.UseCookieAuthentication(new CookieAuthenticationOptions
{ DataProtectionProvider = DataProtectionProvider.Create(new DirectoryInfo(#"c:\shared-auth-ticket-keys\"))
});
Then configure your ASP.NET 4.7.2 application by following steps below:
Install the package Microsoft.Owin.Security.Interop into your ASP.NET 4.7.2 application.
In Startup.Auth.cs, locate the call to UseCookieAuthentication, which will generally look like the following:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
// ...
});
Modify the call to UseCookieAuthentication as follows, changing the AuthenticationType and CookieName to match those of the ASP.NET Core cookie authentication middleware, and providing an instance of a DataProtectionProvider that has been initialized to a key storage location.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
CookieName = ".AspNetCore.Cookies",
// CookiePath = "...", (if necessary)
// ...
TicketDataFormat = new AspNetTicketDataFormat(
new DataProtectorShim(
DataProtectionProvider.Create(new DirectoryInfo(#"c:\shared-auth-ticket-keys\"))
.CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware",
"Cookies", "v2")))
});
The DirectoryInfo has to point to the same storage location that you pointed your ASP.NET Core application to and should be configured using the same settings.
In IdentityModels.cs, change the call to ApplicationUserManager.CreateIdentity to use the same authentication type as in the cookie middleware.
public ClaimsIdentity GenerateUserIdentity(ApplicationUserManager manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = manager.CreateIdentity(this, "Cookies");
// ...
}
Reference:
Share authentication cookies among ASP.NET apps
Share authentication cookies between ASP.NET 4.x and ASP.NET Core apps
i try to do an angular application with MSAL-angular and Azure B2C for authentication.
I am able to authenticate the angular app with Azure B2C (i have create a susi flow) and obtain the token as show in image below
so i have create a .net core web api project and modify the appsetting configuration and the start up with this code :
appsetting.json :
"AzureAdB2C": {
"Instance": "https://{mytenat}.b2clogin.com/tfp",
"ClientId": "8xxxx-xxxx-xxxx-xxxx-xxxxxxxxc",
"Domain": "{mytenat}.onmicrosoft.com",
"SignUpSignInPolicyId": "B2C_1_susi"
}
startup.cs
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(options =>
{
Configuration.Bind("AzureAdB2C", options);
options.TokenValidationParameters.RoleClaimType = "roles";
options.TokenValidationParameters.NameClaimType = "name";
},
options => { Configuration.Bind("AzureAdB2C", options); });
// By default, the claims mapping will map claim names in the old format to accommodate older SAML applications.
//'http://schemas.microsodt.com/ws/2008/06/identity/clains/role' instead of 'roles'
// This flag ensures that the ClaimsIdentity claims collection will be build from the claims in the token
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
//services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
//{
// // The claim in the Jwt token where App roles are available.
// options.TokenValidationParameters.RoleClaimType = "roles";
//});
but if i try to run localy the project and call it with postman i have this error :
**System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token. **
i don't understand where is the error.
can you help me?
thanks
In your question, you have created a web api application and angular app in Azure AD B2C. Next, you need to expose the api of the web api application, and then add permissions to the angular app.
First go to web api.
Then go to angular app>API permissions> add a permission>My APIs>your web api app.
Finally, when you parse the token, you will see the scp:access claim.
I have an ASP.NET Core MVC application and I integrated Azure AD into it using the following code:
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.Authority = options.Authority + "/v2.0/";
options.TokenValidationParameters.ValidateIssuer = true;
});
The Azure AD Configuration contains these properties:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]",
"TenantId": "<tenant-id>",
"ClientId": "<client-id>",
"CallbackPath": "/signin-oidc"
},
"DownstreamApi": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "user.read User.ReadBasic.All"
}
It all worked locally and when deployed to an Azure App Service we did not have any problems.
I needed to integrate Microsoft Graph for a new module in the Web App (I need to look up the users in specific groups of the Azure AD).
I followed the Microsoft Graph Tutorial to implement Microsoft Graph.
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
// Handling SameSite cookie according to https://learn.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-3.1
options.HandleSameSiteCookieCompatibility();
});
// Sign-in users with the Microsoft identity platform
string[] initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
It all works locally but as soon as the app is deployed into an Azure App Service then app goes into a redirect loop when the user is authenticated.
I reversed the changes to the original code and it gets fixed but then I can't use Microsoft Graph because I do not have the access token.
I checked all the redirect urls in the App Registration and they seem to be fine. I even included
https://<app-name>.azurewebsites.net/
in addition to
https://<app-name>.azurewebsites.net/sigin-oidc
just to be sure it wasn't a redirect url issue.
I thought it was the Katana bug but that seems to have been fixed in .NET Core.
I enabled HTTPS Only on the Azure App Service but the issue still persists.
Has anyone experienced something like this issue? I've been at it for a couple of days and I can't solve it.
Any helped is greatly appreciated.
I tried publishing the microsoft tutorial linked in the question to a new Azure App Service with a new App Registration in Azure AD.
It signed in without a problem.
After that I suspected that there might be a problem with the App Registration. I came to that conclusion because the Azure AD Registration that the MVC Web App was using was created directly in Visual Studio and not manually in the Azure Portal.
Finally, all I did was create a new App Registration in Azure AD and published the MVC Web App with the new client secret and client id. Everything seem to work fine on the published Azure App Service.
I have issue in azure ad authentication when I build application using visual studio 2017 integration with azure ad and deployed in to azure.
the problem is when sign using our aazure ad to login username and password after that they send token our mobile when we enter that toke some my applixation is working, some time error we couldn't sign you try again could you tell me issue.this issue is coming time to time.
when I rebuild project and deployed again it is working next with two hours same error is coming I couldn't find the solution why this error occured could please help me
The problem has been fixed in ASP.NET core and in the new version of Katana Owin for ASP.NET. To resolve this issue, you can upgrade your application to use ASP.NET Core. If you must continue stay on ASP.NET, perform the following:
Update your application’s Microsoft.Owin.Host.SystemWeb package be at least version and modify your code to use one of the new cookie manager classes, for example something like the following:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
CookieManager = new Microsoft.Owin.Host.SystemWeb.SystemWebChunkingCookieManager()
});
How we can check token expire in mvc startup class
You could use Properties.ExpiresUtc to get the access token expiration time.
options.Events = new OpenIdConnectEvents
{
OnTokenValidated = x =>
{
x.Properties.IsPersistent = true;
var accessToken = new JwtSecurityToken(x.TokenEndpointResponse.AccessToken);
x.Properties.ExpiresUtc = accessToken.ValidTo;
return Task.CompletedTask;
}
};
Also you could silent renew access_token via refresh_token in asp.net core mvc, refer to this SO thread.
I am trying to authenticate CORS origin requests and set Claims principle with the user of internal company single sign on utility. I have the current setting so far, the cookie will never get created on the domain set at the authentication setup.
I have an Angular client application and .Net Core 3.0 Webapi, the requirement is for the client to be able to set authentication for future api calls.
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.Cookie.Name = "access_token";
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.Domain = "localhost:xxxx";
});
//CORS
services.AddCors(options =>
{
options.AddPolicy(
"AllowOrigin",
builder => builder.WithOrigins("localhost:xxxx")
.AllowCredentials()
.AllowAnyHeader()
.AllowAnyMethod());
});
//Sign In
HttpContext.SignInAsync(
scheme: CookieAuthenticationDefaults.AuthenticationScheme,
principal: new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme)),
properties: new AuthenticationProperties { ExpiresUtc = DateTime.Now.Add(120) });
I am testing this all on local so both URLS are localhost with different ports
Angular is hosted: http://localhost:xxxx
WebAPi is hosted :http://localhost:xxx2
http request from Angular to webapi is http://localhost:xxx2/api/auth which has the SignInAsync call, the company single sign does a username but the cookie never gets created. If I remove the options.Cookie.Domain = "localhost:xxxx"; the cookie does get created on the webapi domain http://localhost:xxx2. I must be missing something here.
After reading up some other posts on stackoverflow , it tuned out that AllowAllOrigins will only fix this problem but poses a threat.
So I ended up fixing this issue with JWT - setting authorization token for every request sent from client interface. This issue was caused due to fact that the client and WebApi are hosted on different domains.