Identity Server 4 - Role claims missing in OpenIdConnect handler in MVC client - c#

I know this issue has been reported alot and there are a lot of articles on how to fix this. I've gone through a lot of them and still can't solve this.
I am setting custom claims on the Principal.Identity from within the OnSecurityTokenValidated callback in Identity Server like so:
public async Task SecurityTokenValidated(SecurityTokenValidatedContext context) {
var identity = context.Principal.Identity as ClaimsIdentity;
foreach(var claim in context.Principal.Claims.Where(x = >x.Type == "adGroupClaimType").ToList()) {
var groupName = Configuration.GetSection("ClaimMappings").GetValue < string > ($ "Prefix_{claim.Value}");
if (!string.IsNullOrWhiteSpace(groupName)) {
identity.AddClaim(new Claim(ClaimTypes.Role, groupName));
}
identity.RemoveClaim(claim);
}
}
The following is the configuration I use in Identity Server:
public static IEnumerable < IdentityResource > IdentityResources = >new List < IdentityResource > {
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource("roles", new[] {
ClaimTypes.Role
})
};
public static IEnumerable < ApiScope > ApiScopes = >new List < ApiScope > {
new ApiScope("api", "API")
};
public static IEnumerable < Client > Clients = >new List < Client > {
new Client {
ClientId = "mvc-openid",
ClientSecrets = {
new Secret("secret".Sha256())
},
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RedirectUris = {
"https://localhost:6001/signin-oidc"
},
AllowedScopes = new List < string > {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api",
"roles"
},
RequirePkce = false,
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true
}
};
There's an MVC client which connects to the Identity Server using OpenIdConnect. The code is given below:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddAuthentication(options = >{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
}).AddCookie(options = >{
options.ExpireTimeSpan = 15;
options.SlidingExpiration = true;
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
}).AddOpenIdConnect("oidc", options = >{
options.Authority = "https://localhost:5001";
options.ClientId = "mvc-openid";
options.ClientSecret = "secret";
options.ResponseType = "code id_token token";
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.Scope.Add("api");
options.Scope.Add("roles");
options.Scope.Add("offline_access");
options.Events.OnTokenValidated = OnTokenValidated;
options.TokenValidationParameters = new TokenValidationParameters {
NameClaimType = ClaimTypes.Name,
RoleClaimType = ClaimTypes.Role
};
options.ClaimActions.MapUniqueJsonKey(ClaimTypes.Role, ClaimTypes.Role);
});
}
private Task OnTokenValidated(TokenValidatedContext context) {
var t = context.Principal.Claims;
return Task.CompletedTask;
}
When I inspect the claims inside OnTokenValidated, I could see that all the role claims that I set from Identity Server are missing. Can someone tell me where I am going wrong? I have tried almost everything found on the Stack Overflow threads about this issue. Clueless right now as to what to do next.

I have also only found this solution so far.
options.Events.OnUserInformationReceived = context =>
{
var roleElement = context.User.RootElement.GetProperty("role");
var claims = new List<Claim>();
if (roleElement.ValueKind == System.Text.Json.JsonValueKind.Array)
{
foreach (var r in roleElement.EnumerateArray())
claims.Add(new Claim(JwtClaimTypes.Role, r.GetString()));
}
else
{
claims.Add(new Claim(JwtClaimTypes.Role, roleElement.GetString()));
}
var id = context.Principal.Identity as ClaimsIdentity;
id.AddClaims(claims);
return Task.CompletedTask;
};
https://github.com/skoruba/IdentityServer4.Admin/issues/109

Related

Authentication problem with cookie in ASP .NET Core 6

I'm trying to use the authentication cookie for a successful login.
Here it is how I create a cookie authentication
private async Task<IList<string>> CreatingAuthCookie(ApplicationUser user, bool rememberMe)
{
var rolesUser = await _userManager.GetRolesAsync(user);
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Name, user.NameUser),
new Claim(ClaimTypes.Surname, user.LastNameUser),
new Claim(ClaimTypes.Email, user.Email),
new Claim(ClaimTypes.NameIdentifier, user.Id)
};
foreach (var role in rolesUser)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
var identity = new ClaimsIdentity(claims, "NameCookieIdentity");
var claimsPrincipal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync("NameCookieIdentity", claimsPrincipal, new AuthenticationProperties()
{
IsPersistent = rememberMe,
});
return rolesUser;
}
Here is How it is handled
builder.Services.AddAntiforgery(options => {
options.Cookie.Name = "X-CSRF-TOKEN-NameCookieIdentity";
options.HeaderName = "X-CSRF-TOKEN-NameCookieIdentity";
options.FormFieldName = "X-CSRF-TOKEN-NameCookieIdentity";
});
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
builder.Services.AddAuthentication("NameCookieIdentity").AddCookie("NameCookieIdentity", option =>
{
option.Cookie.Name = "NameCookieIdentity";
option.Cookie.HttpOnly = true;
option.ExpireTimeSpan = System.TimeSpan.FromDays(2);
option.SlidingExpiration = true;
option.LoginPath = "/Identity/User/Login";
option.LogoutPath = "/Identity/User/Logout";
option.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
option.SlidingExpiration = true;
});
builder.Services.AddIdentity<ApplicationUser, IdentityRole >(options =>
{
options.SignIn.RequireConfirmedAccount = true;
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireUppercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequiredLength = 8;
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._#+";
options.Lockout.DefaultLockoutTimeSpan = System.TimeSpan.FromHours(1);
options.Lockout.AllowedForNewUsers = true;
options.Lockout.MaxFailedAccessAttempts = 5;
options.SignIn.RequireConfirmedAccount = true;
options.SignIn.RequireConfirmedEmail = true;
options.User.RequireUniqueEmail = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
And here is how I managed the middleware
app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions()
{
HttpsCompression = Microsoft.AspNetCore.Http.Features.HttpsCompressionMode.Compress,
OnPrepareResponse = (context) =>
{
var headers = context.Context.Response.GetTypedHeaders();
headers.CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
{
Public = true,
MaxAge = TimeSpan.FromDays(7)
};
headers.Expires = DateTime.UtcNow.AddDays(7);
}
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
and so on..
The problem is: When I'm trying to reach an action inside a controller which is protected by the [Authorize] data annotation, this last one don't gives me the access to go inside.
I can access by only remove the data annotation Authorize on the top of the action.
Last thing.
This is How I access to the data stored inside the cookie.
var userId = HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
Even with the a created cookie, by debugging this statement, I can't access to the data inside of the cookie and the var userId is null.
Please help me out and suggest me well staff to manage the authentication as well as possible.
I'm new in stackoverflow so be good with me :)

ASP.NET Core HttpxContext User is null but user is Authenticated

Basically, I can log in just fine in my Client and access all pages. If I log out, I can't access anything on my client, it always redirects to my login page. Directly accessing the api endpoint is another matter. Say I call mylocalapp.com/api/users, directly from the browser url bar, I can still get all data. So I added [Authorize]. Unexpectedly, I get a 401 if I do that, DESPITE being logged in. So I checked HttpContext.User and simply User.Identity and they're empty, despite successful authentication. ClaimsIdentity is also empty. Can you identify anything that I might have done wrong? According to what I found on Google, this IS how it should be done. Thanks for your help.
Login method:
Takes user data, checks if ok, creates a JWT token and gets browser cookies (if null - session expired) then appends the token to the browser. And then logs the user in via Sign In Manager. If ok, returns ok. Context var is just for debugging purposes.
[AllowAnonymous]
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
async public Task<IActionResult> LoginPost(AuthUser authUser)
{
var user = _context.Users.FirstOrDefault(user => user.Email == authUser.Email);
if (authUser is null) return BadRequest(AppResources.NullUser);
if (user is null) return BadRequest(AppResources.UserBadCredentials);
else
{
var isPassword = _userManager.CheckPasswordAsync(user, authUser.Password);
if (!isPassword.Result) return BadRequest(AppResources.UserBadCredentials);
var token = _jwtHandlerAuth.Authentication(authUser);
if (token == null) return BadRequest(AppResources.UserAuthenticationImpossible);
string cookieValue = Request.Cookies["jwt"];
var returnUser = new ReturnUser
{
Email = user.Email,
Name = $"{user.FirstName} {user.LastName}",
UserName = user.UserName
};
if (cookieValue != token)
{
Response.Cookies.Append("jwt", token, new CookieOptions
{
HttpOnly = true,
IsEssential = true,
SameSite = SameSiteMode.None,
Secure = true
});
}
var signInResult = await _signInManager.PasswordSignInAsync(authUser.Email, authUser.Password, false, false);
if (!signInResult.Succeeded) return BadRequest(AppResources.UserAuthenticationImpossible);
var context = _signInManager.Context;
return Ok(returnUser);
}
}
My Authentication method (creates the token):
public string Authentication(AuthUser authUser)
{
var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim("UserName", authUser.Email),
new Claim("Email", authUser.Email)
}),
Expires = DateTime.UtcNow.AddHours(2),
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(Encoding.UTF32.GetBytes(_privateKey)),
SecurityAlgorithms.HmacSha256Signature)
};
var claimsPrincipal = new ClaimsPrincipal(tokenDescriptor.Subject);
var token = tokenHandler.CreateToken(tokenDescriptor);
tokenHandler.WriteToken(token);
return tokenHandler.WriteToken(token);
}
And my Startup class services and middleware:
var builder = services.AddIdentityCore<User>();
var identityBuilder = new IdentityBuilder(builder.UserType, builder.Services);
identityBuilder.AddRoles<IdentityRole>();
identityBuilder.AddEntityFrameworkStores<IdentityContext>();
identityBuilder.AddSignInManager<SignInManager<User>>();
identityBuilder.AddDefaultTokenProviders();
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
x.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddCookie("Identity.Application").AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF32.GetBytes(Configuration.GetSection("Jwt:PrivateKey").Value)),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddSingleton<IJwtHandlerAuth>(new JwtHandlerAuth(Configuration.GetSection("Jwt:PrivateKey").Value));
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

Method not found: System.Threading.Tasks.Task UserInfoResponse when making Http call

I am trying to implement Single Sign On on my old WebForm app. The authentication part succeeds and I receive the access token. In the moment that I try to contact IdentityServer once again with the access token and get further claims regarding the logged user, then I have a problem. My code at startup looks like this:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = "http://localhost:50001",
RedirectUri = "http://localhost:65438/signin-oidc",
PostLogoutRedirectUri = "http://localhost:65438/signout-callback-oidc",
RequireHttpsMetadata = false,
ClientId = "webforms",
AuthenticationType = "oidc",
SignInAsAuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
ResponseType = "id_token token",
Scope = "openid profile email",
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async n =>
{
var claimsToExclude = new[]
{
"aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash"
};
var claimsToKeep = n.AuthenticationTicket.Identity.Claims.Where(x => !claimsToExclude.Contains(x.Type)).ToList();
claimsToKeep.Add(new Claim("id_token", n.ProtocolMessage.IdToken));
if (n.ProtocolMessage.AccessToken != null)
{
claimsToKeep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("http://localhost:50001");
var userInfoResponse = await client.GetUserInfoAsync(new UserInfoRequest
{
Address = disco.UserInfoEndpoint,
Token = n.ProtocolMessage.AccessToken
});
var userInfoClaims = userInfoResponse.Claims
.Where(x => x.Type != "sub"); // filter sub since we're already getting it from id_token
claimsToKeep.AddRange(userInfoClaims);
}
var ci = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType, "name", "role");
ci.AddClaims(claimsToKeep);
n.AuthenticationTicket = new Microsoft.Owin.Security.AuthenticationTicket(ci, n.AuthenticationTicket.Properties);
},
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
n.ProtocolMessage.IdTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token")?.Value;
}
return Task.FromResult(0);
}
}
});
The specific part where the problem happens is this:
if (n.ProtocolMessage.AccessToken != null)
{
claimsToKeep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("http://localhost:50001");
var userInfoResponse = await client.GetUserInfoAsync(new UserInfoRequest
{
Address = disco.UserInfoEndpoint,
Token = n.ProtocolMessage.AccessToken
});
var userInfoClaims = userInfoResponse.Claims
.Where(x => x.Type != "sub"); // filter sub since we're already getting it from id_token
claimsToKeep.AddRange(userInfoClaims);
}
Since this is in a middleware it's not very easy to debug it but the exception happening is this one:
Method not found: 'System.Threading.Tasks.Task`1<IdentityModel.Client.UserInfoResponse> IdentityModel.Client.HttpClientUserInfoExtensions.GetUserInfoAsync(System.Net.Http.HttpMessageInvoker, IdentityModel.Client.UserInfoRequest, System.Threading.CancellationToken)'.
Any suggestions? Thanks in advance!

Provider claims in IProfileService

When I auth using oidc I get back a bunch of claims. If I do not add my custom IProfileService all of these claims are passed through in the id_token that identity server issues. If I provide my own ProfileService, the list of claims on the Subject is a subset of what comes back from the idp. Is there any way to get the full list in the profile service?
Here is the relevant info from Startup.cs:
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
}).AddProfileService<ProfileService>();
services.AddAuthentication()
.AddOpenIdConnect("Name", "Name", o =>
{
o.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
o.SignOutScheme = IdentityServerConstants.SignoutScheme;
o.Authority = "https://sub.domain.com/adfs/";
o.ClientId = "00000000-0000-0000-0000-000000000000";
o.ClientSecret = "secret";
o.ResponseType = "id_token";
o.SaveTokens = true;
o.CallbackPath = "/signin-adfs";
o.SignedOutCallbackPath = "/signout-callback-adfs";
o.RemoteSignOutPath = "/signout-adfs";
o.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
and my ProfileService:
public class ProfileService : IProfileService
{
public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var objectGuidClaim = context.Subject.Claims.FirstOrDefault(x => x.Type == "ObjectGUID");
if (objectGuidClaim != null)
{
var userId = new Guid(Convert.FromBase64String(objectGuidClaim.Value));
context.IssuedClaims.Add(new Claim("UserId", userId.ToString()));
}
return Task.CompletedTask;
}
public Task IsActiveAsync(IsActiveContext context)
{
context.IsActive = true;
return Task.CompletedTask;
}
}
So in my case, without the ProfileService then ObjectGUID is passed through, but using the ProfileService, it's not available in context.Subject.Claims list.
My goal is to take the "ObjectGUID" claim from the idp which is a base64 encoded guid and convert it to a hex string and pass that along as the "UserId" claim from identity server.
I'm not even sure this is the best way. I've also tried converting it through ClaimActions but my action never executes (I tested with a random guid to make sure it wasn't something with the conversion):
o.ClaimActions.MapCustomJson("UserId", obj => {
return Guid.NewGuid().ToString();
});
Is this a better way? Why is it not executing?
Try to:
ensure your Subject does not contain
http://schemas.company.com/identity/claims/objectguid instead of just ObjectGUID
extend your
OpenIdConnect configuration with: o.GetClaimsFromUserInfoEndpoint =
true; together with o.ClaimActions.MapUniqueJsonKey("ObjectGUID", "ObjectGUID"); or o.ClaimActions.MapUniqueJsonKey("http://schemas.company.com/identity/claims/objectguid", "ObjectGUID");
if nothing before helped, try:
o.Events = new OpenIdConnectEvents
{
OnTicketReceived = context =>
{
var identity = context.Principal.Identity as ClaimsIdentity;
StringBuilder builder = new StringBuilder();
var claims = identity?.Claims.Select(x => $"{x.Type}:{x.Value};");
if (claims != null)
builder.AppendJoin(", ", claims);
Logger.LogInformation($"Ticket received: [Claims:{builder}]");
identity?.AddClaim(new Claim("userId", Guid.NewGuid().ToString()));
//you can embed your transformer here if you like
return Task.CompletedTask;
}};
(you can examine the exact incoming ticket here and leave the logging anyway for future purposes)

asp.net mvc and apx in one project with owin

I need to add an aspx page into my mvc project, but I always get 404. I founded that in web.config there is owin http handler registration
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb" />
If I commented this my aspx page works fine.
So where can be problem?
Here is my Startup's code:
public void Configuration(IAppBuilder app)
{
app.UseStaticFiles();
Dictionary<string, string> mapping = new Dictionary<string, string>
{
{".apk", "application/vnd.android.package-archive"}
};
StaticFileOptions options = new StaticFileOptions
{
ContentTypeProvider = new FileExtensionContentTypeProvider(mapping)
};
app.UseStaticFiles(options);
LogProvider.SetCurrentLogProvider(new Log4NetLogProvider());
HttpConfiguration config = new HttpConfiguration();
ODataConventionModelBuilder builder = new ODataConventionModelBuilder
{
Namespace = "blabla",
ContainerName = "blabla"
};
builder.EntitySet<Common.DataAccess.Sharepoint.Users>("Users");
var departmentSet = builder.EntitySet<Common.DataAccess.Sharepoint.Departments>("Department");
builder.EntitySet<Common.DataAccess.Sharepoint.Roles>("Roles");
var dependentFunction = departmentSet.EntityType.Collection.Function("GetChilds");
dependentFunction.Parameter<int>("parent");
dependentFunction.ReturnsCollectionFromEntitySet<Common.DataAccess.Sharepoint.Departments>("Department");
var allUsers = departmentSet.EntityType.Collection.Function("GetAllDependenUsers");
allUsers.Parameter<int>("department");
allUsers.Parameter<string>("query");
allUsers.ReturnsCollectionFromEntitySet<Common.DataAccess.Sharepoint.Users>("Users");
config.MapODataServiceRoute("orgstructure", "orgstructure", builder.GetEdmModel());
app.UseWebApi(config);
AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
SecureString password = new SecureString();
foreach (char c in "idsrv3test")
password.AppendChar(c);
IdentityServerOptions identityServerOptions = new IdentityServerOptions
{
SiteName = "123123",
Factory = new IdentityServerServiceFactory
{
UserService = new Registration<IUserService>(typeof (IdentityUserService)),
ScopeStore = new Registration<IScopeStore>(typeof (IdentityScopeStore)),
ClientStore = new Registration<IClientStore>(typeof (IdentityClientStore))
},
RequireSsl = false,
CspOptions = new CspOptions
{
Enabled = false
},
SigningCertificate = new X509Certificate2(Assets.idsrv3test, password),
CorsPolicy = CorsPolicy.AllowAll,
AuthenticationOptions = {EnablePostSignOutAutoRedirect = true}
};
identityServerOptions.Factory.Register(new Registration<IUserRoleService, UserRolesService>());
identityServerOptions.Factory.Register(new Registration<IUserDepartmentsService, UserDepartmentsService>());
app.Map("/open_id", idsrvApp =>
{
identityServerOptions.Factory.ConfigureDefaultViewService(new DefaultViewServiceOptions
{
CacheViews = true,
ViewLoader = new Registration<IViewLoader, IdentityViewLoader>()
});
idsrvApp.UseIdentityServer(identityServerOptions);
});
app.UseCookieAuthentication(new CookieAuthenticationOptions {AuthenticationType = "Cookies"});
string baseUrl = ConfigurationManager.AppSettings["RedirectUrl"];
string clientName = ConfigurationManager.AppSettings["ClientName"];
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(Constants.StandardScopes.OpenId);
stringBuilder.Append(" ");
stringBuilder.Append(Common.Constants.Scopes.Portal);
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = baseUrl + "open_id",
ClientId = clientName,
Scope = stringBuilder.ToString(),
ResponseType = "id_token",
SignInAsAuthenticationType = "Cookies",
RedirectUri = baseUrl,
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = n =>
{
var id = n.AuthenticationTicket.Identity;
// create new identity and set name and role claim type
var nid = new ClaimsIdentity(id.AuthenticationType, ClaimTypes.GivenName, ClaimTypes.Role);
IEnumerable<Claim> claims = id.Claims
.Where(x => x.Type != Common.Constants.Claims.Role && x.Type != Common.Constants.Claims.PortalRole);
nid.AddClaims(claims);
nid.AddClaims(id.Claims.Where(x => x.Type == Common.Constants.Claims.Role)
.Select(x => new Claim(ClaimTypes.Role, x.Value, x.ValueType, x.Issuer, x.OriginalIssuer))
);
nid.AddClaims(id.Claims.Where(x => x.Type == Common.Constants.Claims.PortalRole)
.Select(x => new Claim(ClaimTypes.Role, x.Value, x.ValueType, x.Issuer, x.OriginalIssuer))
);
nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
n.AuthenticationTicket = new AuthenticationTicket(nid, n.AuthenticationTicket.Properties);
return Task.FromResult(new object());
},
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.AuthenticationRequest)
{
var baseAddress = new Uri(n.ProtocolMessage.IssuerAddress);
if (baseAddress.Host != n.Request.Uri.Host)
{
var uriBuilder = new UriBuilder(baseAddress) {Host = n.Request.Uri.Host};
n.ProtocolMessage.IssuerAddress = uriBuilder.Uri.ToString();
}
var redirectBaseAddress = new Uri(n.ProtocolMessage.RedirectUri);
if (redirectBaseAddress.Host != n.Request.Uri.Host)
{
var uriBuilder = new UriBuilder(redirectBaseAddress) { Host = n.Request.Uri.Host };
n.ProtocolMessage.RedirectUri = uriBuilder.Uri.ToString();
}
}
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;
n.ProtocolMessage.IdTokenHint = idTokenHint;
}
return Task.FromResult(new object());
}
}
});
}
As long as you will use OwinHttpHandler you will not be able to serve aspx pages. This happens because instead of letting aspx request to reach webforms handler, you impose it to be processed by OwinHttpHandler that doesn't know how to handle aspx. So the solution, as you empirically saw, is to eliminate handler adding from web.config.

Categories