Authenticating swagger with identityserver3 using .net 4.5 - c#

I am having some issues getting swagger to work with oauth2.
I have created a client in my database like this:
private static void CreateSwaggerClient(DatabaseContext context)
{
var client = new Client
{
ClientId = "swaggerui",
ClientName = "Swagger UI client",
Flow = Flows.Implicit,
Enabled = true,
EnableLocalLogin = true,
AccessTokenType = AccessTokenType.Reference,
AllowAccessTokensViaBrowser = true,
IdentityTokenLifetime = 300,
AccessTokenLifetime = 3600,
AuthorizationCodeLifetime = 300,
AbsoluteRefreshTokenLifetime = 2592000,
SlidingRefreshTokenLifetime = 1296000,
RedirectUris = new List<ClientRedirectUri>
{
new ClientRedirectUri { Uri = "http://localhost:62668/swagger" }
},
AllowedScopes = new List<ClientScope>()
{
new ClientScope
{
Scope = "api"
}
},
ClientSecrets = new List<ClientSecret>()
{
new ClientSecret
{
Value = "secret".Sha256(),
Type = "SharedSecret"
}
}
};
context.Clients.Add(client);
context.SaveChanges();
}
Which has access to my api Scope:
private static void CreateScope(DatabaseContext context)
{
var scope = new Scope
{
Enabled = true,
Name = "api",
DisplayName = "Cormar API",
Description = "Should only be used for trusted internal service side applications",
Required = true,
Emphasize = true,
Type = (int)ScopeType.Resource,
IncludeAllClaimsForUser = false,
ShowInDiscoveryDocument = true,
AllowUnrestrictedIntrospection = true,
ScopeClaims = new List<ScopeClaim>()
{
new ScopeClaim
{
Name = "role",
Description = "Role claim types",
AlwaysIncludeInIdToken = true
},
new ScopeClaim
{
Name = "name",
Description = "The name of the user",
AlwaysIncludeInIdToken = true
},
new ScopeClaim
{
Name ="password",
Description = "Contains the encrypted password for a user",
AlwaysIncludeInIdToken = true
}
},
ScopeSecrets = new List<ScopeSecret>()
{
new ScopeSecret
{
Value = "anothersecret".Sha256(),
Type = "SharedSecret"
}
}
};
context.Scopes.Add(scope);
context.SaveChanges();
}
If I open a browser and navigate to the authorize url like this: https://localhost:44313/identity/connect/authorize?client_id=swaggerui&redirect_uri=http://localhost:62668/swagger&response_type=token&scope=api&state=moo it takes me to a login page, which when I type the username and password brings me to the swagger page with a access_token appended to the URL like this:
#access_token=b49fe5641519c325c17d248d2372d69f&token_type=Bearer&expires_in=3600&scope=api&state=moo
But the issue here is that if I click anything, the access token is removed from the url and if I try any of my endpoints, they all fail with access denied.
I have setup my swagger config like this:
private static void ConfigureSwagger(HttpConfiguration config)
{
config.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "test API");
var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
var commentsFileName = Assembly.GetExecutingAssembly().GetName().Name + ".XML";
var commentsFile = Path.Combine(baseDirectory, "bin", commentsFileName);
c.IncludeXmlComments(commentsFile);
c.OAuth2("oauth2")
.Description("OAuth2 Implicit Grant")
.Flow("implicit")
.AuthorizationUrl("http://localhost:62668/identity/connect/authorize")
.TokenUrl("http://localhost:62668/identity/connect/token")
.Scopes(scopes =>
{
scopes.Add("api", "api access");
});
c.OperationFilter<AssignOAuth2SecurityRequirements>();
}).EnableSwaggerUi(c =>
{
c.EnableOAuth2Support("swaggerui", "secret", "local", "test");
});
}
Can anyone tell me what I am missing?

I managed to get this working.
First of all, my AssignOAuth2SecurityRequirements was setup incorrectly. I actually found the right code here: http://knowyourtoolset.com/2015/08/secure-web-apis-with-swagger-swashbuckle-and-oauth2-part-2/
public class AssignOAuth2SecurityRequirements: IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline();
var allowsAnonymous = actFilters.Select(f => f.Instance).OfType<OverrideAuthorizationAttribute>().Any();
if (allowsAnonymous)
return; // must be an anonymous method
//var scopes = apiDescription.ActionDescriptor.GetFilterPipeline()
// .Select(filterInfo => filterInfo.Instance)
// .OfType<AllowAnonymousAttribute>()
// .SelectMany(attr => attr.Roles.Split(','))
// .Distinct();
if (operation.security == null)
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
{
{"oauth2", new List<string> {"api"}}
};
operation.security.Add(oAuthRequirements);
}
}
Next, the redirect_uris for my client were incorrect. They all have to be https and they need the full redirect uri. Mine became this:
new ClientRedirectUri { Uri = "https://localhost:44313/swagger/ui/o2c-html" },
Once these were set up, it all started working.

Related

Logout from ASP.NET MVC client app and a .NET 5 openiddict server. Post logout redirect url invalid

I'm using OWIN 4.2 with .NET Framework 4.7.2 for my ASP.NET MVC client app.
Login works completely fine but logout will fail.
On my client's startup.cs
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = "MVC",
ClientSecret = "MVC-Secret",
Authority = "https://localhost:44305/",
RedirectUri = "https://localhost:44347/",
CallbackPath = new PathString("/"),
Scope = "openid api",
SignInAsAuthenticationType = "cookie",
RequireHttpsMetadata = false,
UseTokenLifetime = false,
RedeemCode = true,
SaveTokens = true,
ResponseType = OpenIdConnectResponseType.Code,
ResponseMode = OpenIdConnectResponseMode.Query,
// OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to the OnAuthenticationFailed method
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
{
// generate code verifier and code challenge
var codeVerifier = CryptoRandom.CreateUniqueId(32);
string codeChallenge;
using (var sha256 = SHA256.Create())
{
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
codeChallenge = Base64Url.Encode(challengeBytes);
}
// set code_challenge parameter on authorization request
n.ProtocolMessage.SetParameter("code_challenge", codeChallenge);
n.ProtocolMessage.SetParameter("code_challenge_method", "S256");
// remember code verifier in cookie (adapted from OWIN nonce cookie)
// see: https://github.com/scottbrady91/Blog-Example-Classes/blob/master/AspNetFrameworkPkce/ScottBrady91.BlogExampleCode.AspNetPkce/Startup.cs#L85
RememberCodeVerifier(n, codeVerifier);
}
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint;
}
}
return Task.CompletedTask;
},
AuthorizationCodeReceived = n =>
{
// get code verifier from cookie
// see: https://github.com/scottbrady91/Blog-Example-Classes/blob/master/AspNetFrameworkPkce/ScottBrady91.BlogExampleCode.AspNetPkce/Startup.cs#L102
var codeVerifier = RetrieveCodeVerifier(n);
// attach code_verifier on token request
n.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier);
return Task.CompletedTask;
},
SecurityTokenValidated = n =>
{
var id = n.AuthenticationTicket.Identity;
id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
n.AuthenticationTicket = new AuthenticationTicket(
id,
n.AuthenticationTicket.Properties);
return Task.FromResult(0);
},
}
}
);
I also tried
...
Authority = "https://localhost:44305/",
RedirectUri = "https://localhost:44347/",
PostLogoutRedirectUri = "https://localhost:44347/signout-callback-oidc",
...
And also
...
Authority = "https://localhost:44305/",
RedirectUri = "https://localhost:44347/",
PostLogoutRedirectUri = "https://localhost:44347/",
...
However, all these results in the response
error:invalid_request
error_description:The specified 'post_logout_redirect_uri' is invalid.
error_uri:https://documentation.openiddict.com/errors/ID2052
On my server, the configuration is as follows
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = clientId,
ClientSecret = clientSecret,
DisplayName = displayName,
RedirectUris =
{
new Uri("https://localhost:44347/")
},
Permissions =
{
...
},
PostLogoutRedirectUris =
{
new Uri("https://localhost:44347/")
}
}, cancellationToken);
}
I have also tried changing Server config to
PostLogoutRedirectUris =
{
new Uri("https://localhost:44347/signout-callback-oidc")
}
I encountered the same issue, what solved it for me was to add the logout permission in the application - OpenIddictConstants.Permissions.Endpoints.Logout
await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = "mvc",
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
DisplayName = "MVC client application",
PostLogoutRedirectUris = { new Uri("http://localhost:53507/signout-callback-oidc") },
RedirectUris = { new Uri("http://localhost:53507/signin-oidc") },
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Logout,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode
}
});
As answered by Apps in here https://stackoverflow.com/a/69671657/6477254, I can confirm that you must allow permission for the logout endpoint, using the constant value of OpenIddictConstants.Permissions.Endpoints.Logout, which hold "ept:logout" string value when creating the OpenIddict data.

Azure Devops GitHttpClient's CreateAnnotatedTagAsync API fails

When calling GitHttpClient.CreateAnnotatedTagAsync, I keep getting "VS30063: You are not authorized to access https://dev.azure.com" even though my credentials are valid.
This is my code:
var vssConnection = new VssConnection(new Uri("ORG_URI"), new VssBasicCredential(string.Empty, "PAT"));
var gitClient = vssConnection.GetClient<GitHttpClient>();
var tag = new GitAnnotatedTag
{
Name = "tagname",
Message = "A new tag",
TaggedBy = new GitUserDate
{
Name = "Name",
Email = "Email",
Date = DateTime.Now,
ImageUrl = null
},
ObjectId = "SHA",
TaggedObject = new GitObject
{
ObjectId = "SHA",
ObjectType = GitObjectType.Commit
},
Url = string.Empty
};
var sourceRepo = await gitClient.GetRepositoryAsync("PROJECT", repoName);
// This call works
var tags = await gitClient.GetTagRefsAsync(sourceRepo.Id);
// The tag is printed to the console
Console.WriteLine(tags.First().Name);
// This throws "VS30063: You are not authorized to access https://dev.azure.com"
await gitClient.CreateAnnotatedTagAsync(tag, "PROJECT", sourceRepo.Id);
There is an issue with your PAT token. I just created a tag using your code and PAT with FULL Access:
Can you create a new token and try again?

How can I implement PersistedGrantStore on a mongodb database?

I am trying to implement PersistedGrantStore on mongodb. I have seen similar questions and answers but no luck so far (How can I implement PersistedGrantStore on my mongodb database).
I have created a class inhertied from IPersistedGrantStore I have inject it in DI using AddTransient, but still no call is made within my class. Here is a section of my code within ConfigureServices(IServiceCollection services) function of startup.cs
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
o.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
}).AddIdentityServerAuthentication(options =>
{
options.SaveToken = true;
options.Authority = authorityServerURL;// "https://demo.identityserver.io";
//options.ApiName = "BWalle_API";
//options.ApiSecret = "Odsdffegfgdfgdfglq_";
options.RequireHttpsMetadata = false;
options.EnableCaching = false;
options.SupportedTokens = SupportedTokens.Jwt;
});
var builder = services.AddIdentityServer(options =>
{
options.Endpoints.EnableUserInfoEndpoint = true;
options.Events = new EventsOptions()
{
RaiseErrorEvents = true,
RaiseFailureEvents = true,
RaiseInformationEvents = true,
RaiseSuccessEvents = true
};
})
.AddTestUsers(Config.GetUsers())
.AddSigningCredential(new Microsoft.IdentityModel.Tokens.SigningCredentials(GetSecurityKey(), SecurityAlgorithms.RsaSha512Signature))
.AddResourceStore<ResourceStore>()
.AddClientStore<ClientStore>()
.AddProfileService<MongoDbProfileService>()
.AddResourceOwnerValidator<MongoDbResourceOwnerPasswordValidator>()
.AddJwtBearerClientAuthentication();
builder.Services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();
And this is the ClientStore Class:
public class ClientStore : IClientStore
{
Task<Client> IClientStore.FindClientByIdAsync(string clientId)
{
Client client = new Client
{
ClientId = "BWalle_API",
ClientName = "BWalle API Client",
//AllowAccessTokensViaBrowser = true,
//AlwaysSendClientClaims = true,
AllowedGrantTypes = new List<string>() {
GrantType.ResourceOwnerPassword,
GrantType.Hybrid,
GrantType.ClientCredentials
},
ClientSecrets = new List<Secret>
{
new Secret("Odsdffegfgdfgdfglq_".Sha512())
},
AllowedScopes = new List<string>
{
IdentityServer4.IdentityServerConstants.StandardScopes.OpenId,
IdentityServer4.IdentityServerConstants.StandardScopes.Profile,
IdentityServer4.IdentityServerConstants.StandardScopes.Email,
IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess,
IdentityServer4.IdentityServerConstants.StandardScopes.Phone,
"BWalle_API"
},
Enabled = true,
//AllowedCorsOrigins = new List<string>
//{
// "http://localhost:4200"
//},
AllowOfflineAccess = true,
AllowRememberConsent = false,
AccessTokenType = AccessTokenType.Jwt,
IdentityTokenLifetime = 3600 * 24, // Lifetime to identity token in seconds (defaults to 300 seconds / 5 minutes)
AccessTokenLifetime = 3600 * 24, //3600, // Lifetime of access token in seconds (defaults to 3600 seconds / 1 hour)
AuthorizationCodeLifetime = 3600 * 24, // Lifetime of authorization code in seconds (defaults to 300 seconds / 5 minutes)
RefreshTokenUsage = TokenUsage.ReUse,
RefreshTokenExpiration = TokenExpiration.Sliding,
UpdateAccessTokenClaimsOnRefresh = true,
IncludeJwtId = true
};
return Task.FromResult<Client>(client);
}
}
And this is the PersistedGrantStore Class:
public class PersistedGrantStore : IPersistedGrantStore
{
private readonly IAppRepository appRepository;
public PersistedGrantStore(IAppRepository DBAppRepository)
{
this.appRepository = DBAppRepository;
}
public Task<IEnumerable<PersistedGrant>> GetAllAsync(string subjectId)
{
throw new NotImplementedException();
}
public Task<PersistedGrant> GetAsync(string key)
{
throw new NotImplementedException();
}
public Task RemoveAllAsync(string subjectId, string clientId)
{
throw new NotImplementedException();
}
public Task RemoveAllAsync(string subjectId, string clientId, string type)
{
throw new NotImplementedException();
}
public Task RemoveAsync(string key)
{
throw new NotImplementedException();
}
public Task StoreAsync(PersistedGrant grant)
{
throw new NotImplementedException();
}
}
I am using those nuget packages:
Identityserver4\2.1.3,
Identityserver4.AccessTokenValidation\2.5.0
Contrib.Microsoft.aspnetcore.identity.mongodb\2.0.5
I have managed successfully to use mongodb to store users and client and now I am trying to store grants instead of using in memory grant stores but no call is made whith in PersistedGrantStore class.
I am using ResourceOwner as GrantType (JWT - Bearer Model).
I can not see what I am missing, any help would be realy helpfull!!!
Solved!!!! What was missing was adding to the scope the 'offline_access' when sending from client to the server the connection request to the endpoint '/connect/token'.
Example of post '/connect/token' with data in body :
client_id=BWalle_API&client_secret=mysecretAPlq_&grant_type=password&scope=BWalle_API offline_access&username=undefined&password=undefined&rememberme=&VerCode=1820-0327-2104-0012

Using Kentor + Windows Authentication on IdentityServer3

I have an IdentityServer3 working with Windows Authentication Service. Now I want to handle the SAML2 protocol on my IdentityServer3 and I saw Kentor could do it for me.
The problem is that Kentor is using OpenID Connect in all samples, I searched a while but i couldn't find any documentation on how to combine Kentor with WindowsAuth. After many tries without success, I come here to ask if it is realy possible and how ?
Here is my (non-working) configuration in Startup.cs :
public void Configuration(IAppBuilder appBuilder)
{
appBuilder.Map("/windows", ConfigureWindowsTokenProvider);
appBuilder.UseIdentityServer(GetIdentityServerOptions());
}
private void ConfigureWsFederation(IAppBuilder pluginApp, IdentityServerOptions options)
{
var factory = new WsFederationServiceFactory(options.Factory);
factory.Register(new Registration<IEnumerable<RelyingParty>>(RelyingParties.Get()));
factory.RelyingPartyService = new Registration<IRelyingPartyService>(typeof(InMemoryRelyingPartyService));
factory.CustomClaimsService = new Registration<ICustomWsFederationClaimsService>(typeof(ClaimsService));
factory.CustomRequestValidator = new Registration<ICustomWsFederationRequestValidator>(typeof(RequestValidator));
var wsFedOptions = new WsFederationPluginOptions
{
IdentityServerOptions = options,
Factory = factory,
};
pluginApp.UseWsFederationPlugin(wsFedOptions);
}
private IdentityServerOptions GetIdentityServerOptions()
{
DefaultViewServiceOptions viewServiceOptions = new DefaultViewServiceOptions();
viewServiceOptions.CustomViewDirectory = HttpContext.Current.Server.MapPath("~/Templates");
viewServiceOptions.Stylesheets.Add("/Content/Custom.css");
IdentityServerServiceFactory factory = new IdentityServerServiceFactory()
.UseInMemoryClients(new List<Client>())
.UseInMemoryScopes(new List<Scope>());
factory.ConfigureDefaultViewService(viewServiceOptions);
factory.UserService = new Registration<IUserService>(resolver => new UserService());
return new IdentityServerOptions
{
SigningCertificate = Certificate.Load(),
Factory = factory,
PluginConfiguration = ConfigureWsFederation,
EventsOptions = new EventsOptions
{
RaiseSuccessEvents = true,
RaiseFailureEvents = true,
},
AuthenticationOptions = new IdentityServer3.Core.Configuration.AuthenticationOptions
{
IdentityProviders = ConfigureIdentityProviders,
EnableLocalLogin = false,
},
RequireSsl = true,
};
}
private void ConfigureIdentityProviders(IAppBuilder app, string signInAsType)
{
ConfigureWSFederationProvider(app, signInAsType);
ConfigureKentorProvider(app, signInAsType);
}
private void ConfigureKentorProvider(IAppBuilder app, string signInAsType)
{
SPOptions spOptions = new SPOptions
{
EntityId = new EntityId("Dropbox"),
};
KentorAuthServicesAuthenticationOptions kentorOptions = new KentorAuthServicesAuthenticationOptions(false)
{
Caption = "Windows",
SignInAsAuthenticationType = signInAsType,
SPOptions = spOptions,
};
IdentityProvider idp = new IdentityProvider(new EntityId("http://stubidp.kentor.se/Metadata"), spOptions)
{
Binding = Saml2BindingType.HttpRedirect,
AllowUnsolicitedAuthnResponse = true,
LoadMetadata = true,
};
kentorOptions.IdentityProviders.Add(idp);
app.UseKentorAuthServicesAuthentication(kentorOptions);
}
private void ConfigureWSFederationProvider(IAppBuilder app, string signInAsType)
{
app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions()
{
AuthenticationType = "windows",
Caption = "Windows",
SignInAsAuthenticationType = signInAsType,
MetadataAddress = serverHost + "windows",
Wtrealm = "urn:idsrv3",
});
}
private void ConfigureWindowsTokenProvider(IAppBuilder app)
{
app.UseWindowsAuthenticationService(new WindowsAuthenticationOptions
{
IdpReplyUrl = serverHost,
SigningCertificate = Certificate.Load(),
EnableOAuth2Endpoint = false,
});
}
This configuration builds, but when I use the Dropbox SSO (using SAML2) I get the exception No Idp with entity id "Dropbox" found.
You've configured "Dropbox" as the identity (EntityId in SAML2 terms) of your application (the one in SpOptions). That should be a URI that identifies your application. The convention is to use the URL to the metadata (~/AuthServices).
You need to add an IdentityProvider with the settings of the dropbox idp. Please also note that an EntityId of "Dropbox" won't work as the SAML2 standard requires an Entity ID to be an absolute URI.

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