Given: A Identity Server which supports implicit and Resource Owner flow. (Config see below)
An Api that uses IdentityServerBearerTokenAuthentication. So it basiucally trades a password for a token which is used for auth
A UI which uses implicit workflow for auth.
Now I'm able to get a bearer token from the identity server with which I can access the protected api method.
Also as a User I'm able to log in with the implicit flow and see protected views.
Problem The Problems comes when a signed in WebFrontEndUser wants to access a protected API.
The User signs in in the ui with the implicit flow. After he is authenticated he tries to access a protected api. The Api returns that he is not authorized.
How can I configure the environment so that the api uses the openid information from the user cookie?
Website Confing
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "foo_implicit",
Authority = identServer,
RedirectUri = "http://localhost/foo/",
ResponseType = "token id_token",
Scope = "openid profile",
SignInAsAuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
});
WebApi Config
app.UseIdentityServerBearerTokenAuthentication(new IdentityServer3.AccessTokenValidation.IdentityServerBearerTokenAuthenticationOptions()
{
Authority = identServer
});
IdentityServer Client Config
new Client
{
Enabled = true,
ClientId = "foo_implicit",
ClientName = "foo Site",
ClientSecrets = new List<Secret>
{
new Secret("foo".Sha256())
},
Flow = Flows.Implicit,
AllowedScopes = new List<string>
{
Constants.StandardScopes.OpenId,
Constants.StandardScopes.Profile,
"read"
},
RedirectUris = new List<string>()
{
"http://localhost/foo/"
}
},
new Client
{
Enabled = true,
ClientId = "foo",
ClientName = "foo api",
ClientSecrets = new List<Secret>
{
new Secret("foo".Sha256())
},
Flow = Flows.ResourceOwner,
AllowedScopes = new List<string>
{
Constants.StandardScopes.OpenId,
"read"
}
}
Using OpenID Connect you can request both Identity and Access Tokens during authentication. You are already getting an access token during authentication (response type token
), so I would grab this and use it to access then API. This would prevent the need for a separate Resource Owner client.
You can grab this access token using the the OpenIdConnectAuthenticationNotifications
property of OpenIdConnectAuthenticationOptions
, e.g.:
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = x =>
{
x.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", x.ProtocolMessage.AccessToken));
return Task.FromResult(0);
}
}
Also your IdentityServerBearerTokenAuthenticationOptions
should state one or more Scopes that a token requires for access. Otherwise any access token from that authority can access your API. See documentation for more details on this.
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = identServer,
RequiredScopes = new[] { "api1" }
});