Skip to content
This repository has been archived by the owner on Sep 18, 2021. It is now read-only.

Use Case for Multiple Applications #474

Closed
stevenfirstrowinc opened this issue Oct 24, 2014 · 23 comments
Closed

Use Case for Multiple Applications #474

stevenfirstrowinc opened this issue Oct 24, 2014 · 23 comments
Assignees
Labels

Comments

@stevenfirstrowinc
Copy link

When I originally discovered this product I had envisioned using it as a single STS for multiple applications, probably due to my misunderstanding of the term client. Now that I'm more familiar with the terms etc. I'm not sure my use case is valid. Primarily I'm having trouble understanding how I map a user's roles to a specific scope.

Is my use case valid? Is there a built-in way of mapping users' permissions to a specific Scope?

Perhaps I still have some of the concepts wrong in my head here, but I haven't been able to sort it out by reading the documentation. Any help would be appreciated.

@brockallen
Copy link
Member

Identity is different than permissions. An OIDC OP provides identity and the RP decides if the end user or client application is allowed to access the application. Usually the RP makes this decision based upon permissions, which are rules and/or configuration within the RP.

@stevenfirstrowinc
Copy link
Author

I was under the impression that Id Server 3 was going to roll Id Server and Authorization into one. Didn't Authorization Server play the role of RP previously?

@brockallen
Copy link
Member

IdentityServer3 is an OIDC OpenID provider and an OAuth2 authorization server.

An OAuth2 authorization server is a mechanism to allow a user to say what permissions they allow an untrusted 3rd party application to have on their behalf. This is still different than what permissions the user is allowed to perform within an application. Typically these two things are used for different types of applications (consumer vs. enterprise).

There's more to it than this, but it's a start given your questions. Feel free to ask more.

@stevenfirstrowinc
Copy link
Author

So is there still a place for authorization server in this stack? Having a secure token service still is a big part of where we want to go. Does Identity Server fit that bill? It sounds as though I still need to keep each application's user to role mapping within the application itself.

@leastprivilege
Copy link
Member

If the mapping is application specific you either need to do that in the application or use the extensibility points of identity server to customize the claims generation.

@stevenfirstrowinc
Copy link
Author

Do you have a specific extension point in mind? Can you point it out or describe in general what you are thinking would work?

@leastprivilege
Copy link
Member

In the IClaimsProvider you have full control over the emitted claims.

@stevenfirstrowinc
Copy link
Author

I'll check it out, it looks very promising. Thank you.

@rmbrunet
Copy link

Dominick/Brock, If I understand correctly, you are saying that implementing IClaimsProvider we could go to the database or AD or whatever and get a set of user related Role claims to be included in the Token. But, currently, the DefaultTokenService prevents duplicated Claims in the Access Token. Wouldn't that be a problem for Role Claims?

@leastprivilege
Copy link
Member

no

@leastprivilege leastprivilege self-assigned this Oct 27, 2014
@stevenfirstrowinc
Copy link
Author

I checked out the IClaimsProvider interface and what follows is how I setup my use case. Please will you provide some feedback.

  1. I inherit from DefaultClaimsProvider.
  2. Overriding the GetIdentityTokenClaimsAsync I first call the base method to allow the default rules to kick in then
    • I get a list of Resource Scopes that were Granted (ValidatedScopes.GrantedScopes).
    • I then use this list of Resource scopes and filter all claim types of Role to those whose names begin with the Scope (e.g. - Invoice.MarkPaid, Coupon.Delete, or Customer.Admin)

I'm not sure this is going to bear up as my scopes and applications increase. Using this approach, I must create a Resource Scope for each Resource (endpoint?) I have in each application. Namespacing the Scopes (i.e. - Application.Scope) helps, but it still means the client potentially needs to send a long list of scopes to find out all the user can or can not do. With an ImplicitClient in particular this maybe a problem because of url max length requirements.

Alternatively, I have considered letting the Scope be the name of the application (e.g. - Commerce). I would filter as above, and the requesting client would only ever request a single scope, the application. The Roles that are returned would be the roles the user had been assigned in the underlying role provider.

Again, please will you provide feedback to these approaches?

@leastprivilege
Copy link
Member

I'd rather use more coarse grained scopes. It is also questionable if all app specific roles should be managed at the STS.

@stevenfirstrowinc
Copy link
Author

Sorry Dominick, just so I'm clear; you are saying you prefer the second approach (one or few scopes) that cover large areas of the application?

You also are more inclined to have the application specific roles managed at the application?

@leastprivilege
Copy link
Member

yes and yes.

There is no silver bullet of course - it always depends. But generally speaking that's what I typically do.

@stevenfirstrowinc
Copy link
Author

Thank you for your responses. For now I will take the approach of coarse grained scopes and namespaced roles and give some thought to the rest.

@jonas-stjernquist
Copy link

@stevenfirstrowinc Have you made your mind how to scope claims to different applications (relaying parties)?

I'm new to IdentityServer3 and have multiple MVC applications where users have claims which potentially could conflict and give undesired authorization.

Here is an example with two applications able to send emails and notifications to the users. A user might have access to both applications but should only be able to recieve notifications in Application1. How can we prevent the user from recieving notifications in Application2?

Application1
Claim Type: ApplicationFunctionality
Claim Value: RecieveNotifications
Claim Type: ApplicationFunctionality
Claim Value: RecieveEmails

Application2
Claim Type: ApplicationFunctionality
Claim Value: RecieveEmails

@brockallen
Copy link
Member

This could be logic in your profile service based on the client.

@stevengopmo
Copy link

we ended up using scope to identify the application (per @leastprivilege suggestion) and then namespacing the roles, e.g. - myapp1.rolename, myapp2.rolename. The myapp1 matches the scope name. Then when the user logs in, depending on what scope they asked for they get their roles filtered by that scope. HTH

@jonas-stjernquist
Copy link

@brockallen I'm will soon start the development using IdentityServer3 and not IdentityServer4, is it possible that you are referring to using IUserService and not the IProfileService (As far as I know only exist in IdentityServer4)?

I'm currently think about if it's correct to use claims in the way I described above across multiple applications, where we sometimes reuse claims for cross-application functionality. I guess it's required to namespace the claims (using the scope name) in order to distinguish claims for different applications and prevent unauthorized access between the applications.

Here is an example of user claim/claim values:

Name: John Doe
Email: [email protected]
PreferedLanguages: English,Swedish,Spanish
ApplicationFunctionality: Application1.RecieveEmails
ApplicationFunctionality: Application2.RecieveEmails
ApplicationFunctionality: Application1.RecieveNotifications
ApplicationFunctionality: Application2.RecieveNotifications
ApplicationFunctionality: Application1.ViewBackorders
ApplicationFunctionality: Application1.DeleteBackorder
ApplicationFunctionality: Application2.SearchProductInformation
CompanyID: 1145
CompanyID: 6785
CompanyName: Acme Inc
ApplicationLicense: Application1.PayingNormalUser
ApplicationLicense: Application2.FreeUser

A user from Company Acme Inc sehave several CompanyID's which is used when filtering data we request from webservices\databases in the data layer. The user have access to multiple applications where he/she could have different levels of functionality depending on what license they have bought in the applications. Some functionality exist in multiple applications but that doesn't mean the user are authorized to same functionality in all applications he/she have access to.

I would appreciate some guidelines about claims, or at point me to some good resources about the subject. I have read and understood that claims primary is used for identity related information (email, name, department, favorite color, shoe size etc), but if no role\permissions styled claims should be used in claims then how should I persist information about what a user should be able to do in the applications (relaying parties) and how should data be filtered in webservices/databases (resource providers) so the user only sees data he/she are authorized to see?

My first thoughts where that the id_token and access token would be convenient to use since they are issued by the STS (IdentityServer3) and persisted in cookies. The tokens are issued by the STS after the STS have done lookup of user account in Active Directory (external identity provider) which contains identity related information together with an lookup in custom database schema containing information about the role\permissions and claims of the user ( using the username of the Active Directory user account).

How should I persist the roles/permissions and claims of a user if not using the tokens (persisted in cookies) provided by IdentityServer?

@tobbie
Copy link

tobbie commented Mar 15, 2017

@stevengopmo you said:

"we ended up using scope to identify the application (per @leastprivilege suggestion) and then namespacing the roles, e.g. - myapp1.rolename, myapp2.rolename. The myapp1 matches the scope name. Then when the user logs in, depending on what scope they asked for they get their roles filtered by that scope. HTH".

Can I please see an example of what you implemented . Looks like what i need.
Thank you

@stevengopmo
Copy link

we inherited from DefaultClaimsProvider and did something like this

var scopeNames = grantedScopes
                .Where(x => x.Type == ScopeType.Resource)
                .Select(x => x.Name);

            var allClaims = claims as List<Claim> ?? claims.ToList();

            var finalRoles = new List<Claim>();
            foreach (var scopeName in scopeNames)
            {
                finalRoles.AddRange(allClaims.Where(claim =>
                    (claim.Type == Constants.ClaimTypes.Role && claim.Value.StartsWith(scopeName)))
                );
            }

            allClaims.RemoveAll(claim => claim.Type == Constants.ClaimTypes.Role && !finalRoles.Contains(claim));

probably not the most elegant, but worked for us. In a different app we stored the roles with the application rather than IdSrv and that works better. Anyway best of luck

@tobbie
Copy link

tobbie commented Mar 20, 2017

@stevengopmo thanks for this. You mentioned namespacing roles. Did you define a custom scope for that, how does the client request that scope.

@stevengopmo
Copy link

we just defined a custom resource scope and the client requested it using the normal methods for requesting a scope. There are plenty of examples in the samples for Idsrv.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

7 participants