Reputation: 81
I have read Dominik's blog post on authentication vs permission modeling using Identity Server (https://leastprivilege.com/2016/12/16/identity-vs-permissions/). Since I am mostly using role based authorization, I am fine using IdentityServer as authentication/authorization endpoint for different client and apis.
My question is how to model Identity and Resource scopes properly? Can client know which roles are allowed for the user on specific resource? If yes, can client know only the user roles for requested resources scopes (and not all roles for all scopes). As far as I understand the concept, if I request claims about the user via UserInfo endpoint, I am receiving claims which are filtered by claimTypes listed inside requested identity scopes. That means that if client requests roles scope (identity scope with role claimtype), UserInfo endpoint will respond with all role claims including other applications.
Let's take simple MVC example, where the MVC client communicates with API via REST.
MVC client (client) uses Cookie/OIDC Auth middleware and requests: ResponseType = "id_token token", Scope = "openid profile api"
.
The API (resource) uses IdentityServerBearerToken Auth middleware and demands: RequiredScopes = "api"
.
The client has UI elements which should be visible based on api role. How can the roles be accessed from client, since the UserInfo endpoint will only return identity scope based claims?
Should client ask the API (resource), which actions are possible? And based on the response show/hide UI elements?
Thank you for any help.
Upvotes: 7
Views: 5064
Reputation: 1
You can put the roles in your id_token. Implement GetProfileDataAsync
and add your roles when:
context.Caller == Constants.ProfileDataCallers.ClaimsProviderIdentityToken
or if you need them on the api you can also add them when:
context.Caller == onstants.ProfileDataCallers.ClaimsProviderAccessToken
If you make use of RequestedClaimTypes
passed in the context you can filter out if a certain identity scope is requested or not.
For access tokens the resource scope matters (the claim types you specify on those scopes are put in the RequestedClaimTypes
for all your requested scopes in the case of
context.Caller == Constants.ProfileDataCallers.ClaimsProviderAccessToken)
Both are called above if you ask for id_token token
The user info endpoint can be called by your api
in case you use reference access token with openid
scope (must be called otherwise you don't have any info) or want more claims than by default in the principal (coming from a jwt access token),
context.Caller == Constants.ProfileDataCallers.UserInfoEndpoint
(here the RequestedClaimTypes
are the ones specified on the resource scopes your access token has access to..). You can also choose to include them in the id_token
when the resource scope is part of the requested scopes, for example "openid myscope
" where myscope is a resource (api for example), by enabling the 'AlwaysIncludeInIdToken
' flag.
Upvotes: 0
Reputation: 3255
Fixed it, I needed to add the openid and profile scopes to the client;
AllowedScopes = new List<string>
{
"customAPI.read",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
Upvotes: -1
Reputation: 2199
So things are different between IdentityServer3 and IdentityServer4. My example below is based on IdentityServer4.
You need to do a few of things:
IdentityResource
that grants access to the role
claim.IdentityResource
in the client's AllowedScopes
IdentityResource
as a scope.So what I did was as follows:
Where I defined my resources:
new IdentityResource
{
Name = "roles",
UserClaims = { JwtClaimType.Role }
}
Defined my client as:
var client = new Client
{
// .. other stuff
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"roles"
}
}
And then used the the following in my javascript client:
new oidc.OidcClient({
// .. other stuff
scope: 'openid profile roles'
});
I was then able to see all the JwtClaimType.Role
claims I'd added to the ClaimPrincipal
in my javascript client.
Upvotes: 2