IdentityServer / IdentityServer3

OpenID Connect Provider and OAuth 2.0 Authorization Server Framework for ASP.NET 4.x/Katana
https://identityserver.github.io/Documentation/
Apache License 2.0
2.01k stars 763 forks source link

When to use a scope, and when to use a claim #67

Closed ciaranj closed 10 years ago

ciaranj commented 10 years ago

I appreciate this is not directly on topic, but I'm struggling a bit in understanding when I would use a scope, vs a claim (or set thereof) within IdSrv3.

My understanding is that claims are statements about a given subject/identity and scopes declare 'access levels'.

I can also see that within IdSrv3 (and presumably OIDC in general) a close relationship exists between scopes + claims. For example the openid scope request will result in a bunch of claims being returned in the tokens and likewise the requested scopes are returned as a 'scope' claim in the access token.

When designing my claims + scopes is there a resource that I should use to decide whether I store something as a claim against the identity or as a scope that can be requested by an application for the identity (and will IdSrv3 support 'both' models!)

(Sorry, I imagine this is obvious to most folks!)

dealproc commented 10 years ago

Brock/Dominick can probably outline this better, but i'll at least try, in case i get it right. Think of scopes as a partitioning tool/device within a service offering. Your clients (Thinking of ResourceOwnerPasswordFlow here) have a client id and hash/password that they use to connect to the Auth Service to receive their token, after validating your Resource (user) credentials. Then when you connect to the service you wish to access, the scopes set within the auth ticket will say if, based on the client you are using, you can even have access to the service.

So, if you have a set of services, and your admin services should only be allowed access from a thick client application, and not an iPhone application, your "client" credential for the iPhone application would not receive the necessary scope it needs to begin the access to your admin service, but the desktop application, given the proper desktop client credential and associated scope, would have access.

From there, you still need to provide the custom business logic to say if the Resource/User can access the data from within the service in question.

ciaranj commented 10 years ago

Ok. This is useful (thank you!) So Scopes are restricted at client level, not at identity level (I can see the 'ScopeRestrictions' property is used to do that.) I had totally missed this.

So to confirm, if I have a widget resource, potentially I might have the following scopes:

So the widget API needs to check that the token presented allows these scopes (as appropriate,) which confirms that the client can 'access' these scopes, and that the subject granted those scopes.

Independently to the scope checks, the widget API then needs to make a decision based on the subject itself, presumably via a claim or set of claims.

These identity claims that are checked could be the subject identifier or a more abstract concept presumably?

So I might also provide a claim of 'cms_admin'. And IdSrv3 would do the restriction on whether a given identity could provide that claim ?

TL;DR. Scopes are restricted at client level, claims are restricted at identity level.

dealproc commented 10 years ago

TL;DR; yes. Scopes are at the client level, claims are at the resource's (user's) level, to the best of my understanding.

The rest, I need to leave in Brock and Dominick's capable hands.

ciaranj commented 10 years ago

ty :)

vobrechkov commented 10 years ago

I'm a little confused but basically what you're saying is that if you have a mobile app (client) and a JavaScript app you can have certain scopes for the mobile clients and others for the JavaScript clients - kind of like different capabilities for different clients/devices/etc. So lets say we have a user named Joe who uses both clients and authenticates with the same identity that has "Read" access (via claims) to resource "A", however, the mobile client isn't scope authorized for that resource so then Joe can't get to the resource in question using the mobile client and only with the JavaScript one due to scope restrictions. Am I understanding you correctly?

ciaranj commented 10 years ago

That seems to match my understanding. The one thing I cannot quite get to grips with is;

Is it possible in IDSrv3 (via the ScopeClaims?) to restrict the authorization request's returned scopes based on both the allowed client scopes AND the associated claims against the end user being authenticated?

leastprivilege commented 10 years ago

I think you are making this all too complicated ;)

Scopes are a way to partition your API space. See the google playground: https://developers.google.com/oauthplayground/

Let's take a simple example - google has a calendar service - and divided it into two scopes:

https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.readonly

Now when a client requests a token for the calendar API - it has to ask for one of the scopes (multiple scopes are allowed as well of course). This information is used in several ways:

1- to create a consent screen so the user is informed what the client is trying to access 2- maybe the token service has a rules engine that determines which client is actually allowed to request which scope (we do that optionally e.g.) 3- the allowed/consented to scopes are embedded in the resulting access token so the API can determine if the client is allowed to access it (they materialize as claims of type scope in a .net consumer)

makes sense?

ciaranj commented 10 years ago

Absolutely :) This all fits perfectly when the resources in question are owned by the end user being authenticated...... but and this might be something I'm doing that just makes no sense :/

The IdSrv3 model (as far as I can tell) only deals with a single resource/audience (other than the user resource/openid profile resource.) (specifically _issueruri/resources)

If I have an API method 'dosomethingdangerous', potentially I would restrict clients from being able to use this feature (via a scope/s), but also a client might be able to do this for some of the end users it authenticates , but not for all of them, i.e. I may not want a specific identity being able to 'dosomethingdangerous'.

As far as I understand, I have two options;

1) Inside the 'dosomethingdangerous' API I employ a separate authorization model based around the claims that identity has (potentially just on the subject identifier) 2) I model the relevant claims back in IdSrv3.

If the latter case, would one expect to have these claims as 'ScopeClaims' and restrict the client's original request for 'dosomethingdangerous' if the identity who is actually authenticating does not have the associated 'ScopeClaim' ?

I'm sorry that this is likely trivial to yourselves, but I appear to be particularly excellent at overcomplicating things

leastprivilege commented 10 years ago

Think of audience as "all APIs that belong to a trust domain" and scopes are used to "partition" that space.

In IdSrv terms - access tokens will always have an audience of "{IssuerUri}/resources" + the requested scopes (as a claim of type scope).

and yes - you are totally right - there are two models - client authorization and user authorization.

In your service you probably always need user authorization (based on identity claims or other arbitrary user specific data). Client authorization is based on client identity and scopes and it is up to you how far you take that (I've seen other systems that only use a single scope and do everything else based on user identity).

and btw - ScopeClaims are only used for OpenID Connect (aka identity) scopes - not for resource scopes. The reason for that is that we need to be able to associate profile/identity claims with a scope for the UserInfo endpoint.

ciaranj commented 10 years ago

@leastprivilege Ok, thank you for clearing it up, I think I've got a good handle on it now. The ScopeClaim architecture for the 'special' OpenId scope threw me a little.

Referring to https://github.com/thinktecture/Thinktecture.IdentityServer.v3/issues/47#issuecomment-40467124 I can see that the intended way to achieve 'associated claims returned based upon requested scopes' would be to provide a bespoke implementation of the IdSrv3' IClaimsProvider.

Thank you :)

leastprivilege commented 10 years ago

Can we close that?

ciaranj commented 10 years ago

Think so.

ciaranj commented 10 years ago

Hi, @leastprivilege Is your earlier comment: "and btw - ScopeClaims are only used for OpenID Connect (aka identity) scopes - not for resource scopes. The reason for that is that we need to be able to associate profile/identity claims with a scope for the UserInfo endpoint"

Still true, as of Beta 2? I just updated and I see that in the samples there are now non-openid scopes with explicit claim associations ? Looking at commits I can see this is due to the re-working of the resource scopes , is it now the case that when a particular resource scope is requested, that will 'automatically' add those claims to the access token?

leastprivilege commented 10 years ago

yea that has changed - you can now use ScopeClaim on both scope types to tell idsrv which claims to make "available". see here: https://github.com/thinktecture/Thinktecture.IdentityServer.v3/wiki/Scope-Model