Input:
A list of managed identity
The name of app role that we are interested, for example User.Read.All on Microsoft Graph API resource.
Output:
All managed identity in this list that have this role assigned either directly or indirectly via AAD group. For the latter, the role is assigned to an AAD group which the managed identity is a member of.
For the direct assignment we can use the following rest endpoint described in the following doc:
https://learn.microsoft.com/en-us/graph/api/serviceprincipal-list-approleassignments?view=graph-rest-1.0&tabs=http
For the latter, we need to be able to list the app role assignment transitively, we have tested the API above, it does not handle the transitive assignment. Interestingly, such transitive capability is available if app role is assigned to an AAD user.
https://learn.microsoft.com/en-us/graph/api/user-list-approleassignments?view=graph-rest-1.0&tabs=http
Our question:
Is there an endpoint that can provide such transitive checking?
We did come up with a work around. It is not perfect but at least it avoids the N rest endpoint call where N is the number of groups a managed identity belongs to.
Call Graph API to find all principals an app role is assigned to using app role list assigned-to endpoint.
https://learn.microsoft.com/en-us/graph/api/serviceprincipal-list-approleassignedto?view=graph-rest-1.0&tabs=http
This will include both the service principal and the AAD group as the assignee. The result is a set called S1.
Call Graph API to find all groups a managed identity belongs to. The result is a set called S2.
Add the principal Id of the managed identity to S2
Calculate the intersection of S1 and S2. If the intersection is empty, the app role is not assigned and if the intersection is non-empty, the app role is assigned. The approach requires two rest calls.
Could you help validate this work around if there is no better solution? It seems to us this is a common use scenario, we wish there is a simple solution than the work around above in the future.
Related
Background:
I have 2 services, A and B, both requiring access to service X, all running on Cloud Run.
Service X requires authentication, since both A and B have their own service accounts, I gave them the invoker role on service X, made sure access tokens are set on headers, so everything works.
Actual question:
I want to restrict access to specific APIs within service X. Ex: I want Service A to be able to only use READ endpoints, but B to be able to also use WRITE endpoints.
Is there any way to include custom scopes or claims to access tokens generated by GCP from service accounts so I can have granular access control at the API level?
Note: I come from an Azure background, where we could setup and API with scopes, and assign those scopes to accounts. Trying to understand if there's an equivalent on GCP.
In gcp we can create a custom role service account while calling API, In your case you need to create 2 service account with custom role, one with viewer role and other with writer or editor role.
Here is a blog explaining the process of creating a service account with custom roles.
While calling an API make sure you are using the correct service accounts for performing read and write operations respectively.
I am working on service to service authentication using the client credentials flow.
I am using keycloak as the authorization server.
Let's say, there are two services S1 and S2.
Every service will allow only certain other services to call its APIs. It might also happen that two different APIs of one service might permit different set of callers.
I have created roles. I have created scopes and mapped the roles to the scope.
When I am passing the scope in the get token call (/realms/realm_name/protocol/openid-connect/token), I am getting the token with roles that are mapped to the passed scope.
What I am not able to figure out is how do I restrict the assignment of different roles to different services?
Only service owner or admin should be able to login to keycloak and should be able to assign the roles corresponding to his/her service to other services. He should not be able to do anything with roles not meant for his service.
Eg:
S1 has owner O1 (a user in keycloak). S1 has three APIs A1, A2 and A3. To call A1 API, caller should have R1 role, and to call A2 API, caller should have R2 role.
Now if service S2 wants to call S1's API A1, only admin or user O1 should be able to attach role R1 to S2's client in keycloak (or add role R1 to scope attached to service client S2).
This might be related to limited access to perform different operations in keycloak.
If I understood your request correctly you can try to use client finer permission. Run keycloak with the following flag:
-Dkeycloak.profile.feature.admin_fine_grained_authz=enabled
Then in your client you can choose which user can do what with the client:
For example, you can client on the permission view and then create a policy based on the user, and then configure the rest accordingly.
You can in the Keycloak official documentation read more about Managing policies.
I'm trying to better understand how to make use of OIDC/OAuth in securing a restful API, but I keep getting lost in terminology. Also when I research this question most of the answers are for Single Page Apps, so for purposes of this question assume the API will not be used for an SPA.
Assumptions:
Customers will access a restful API to interact with <Service>.
It is expected that customers will create automated scripts, or custom application in their own system to call the API.
Once setup it is not expected that there will be a real person who can provide credentials every time the API is called.
<Service> uses a 3rd party IDP to store and manage users.
3rd part IDP implements OIDC/Oauth and that is how it should be integrated into <Service>
Questions:
What OIDC/OAuth flow should be used in this situation?
What credentials should be provided to the customer? client-id/client-secret or something else?
What tokens can/should be used to communicate information about the "user"? E.g. Who they are/what they can do.
How should those tokens be validated?
Can you point me to any good diagrams/resources that explain this specific use case?
Am I missing anything important in the workflow?
It sounds like these are the requirements, if I am not misunderstanding you. The solution contains not just your own code and is more of a data modelling question than an OAuth one.
R1: Your company provides an API to business partners
R2. Business partners call it from their own applications, which they can develop however they see fit
R3. User authentication will be managed by each business partner, resulting in a unique ID per user
R4. You need to map these user IDs to users + resources in your own system
OAUTH
Partner applications should use the client credentials flow to get an access token to call the API. Each business partner would use a different credential for their set of users.
Using your own IDP to store users does not seem to make sense, since you do not seem to have an authentication relationship with the actual end users.
Access tokens issued to business partners would not be user specific by default. It is possible that a custom claim to identify the user could be included in access tokens - this would have to be developed in a custom manner such as via a custom header, since it is not part of the client credentials flow.
Access tokens would be verified in a standard OAuth manner to identify the partner - and possibly the end user.
DATA
Model users in your own system to have these fields, then store resources (such as orders) mapped against the User ID:
User ID (your generated value)
Partner ID (company the user is from)
External User ID (an ID that is easy for partners to supply)
Typically each partner would also have an entry in one of your database tables that includes a Client ID, name etc.
If you can't include a custom User ID claim in access tokens, partners have to tell you what user they are operating on when they call the API, supplying the external user ID:
POST /users/2569/orders
Your API authorization needs to ensure that calls from Partner A cannot access any resources from Partner B. In the above data you have all the fields you need to enable this.
SUMMARY
So it feels like you need to define the interface for your own APIs, based on how they will be called from the back end of partner apps. Hopefully the above hints help with this.
I am running an MVC5 project that authenticates with claims received from ADFS.
For a specific claim type, I need to include a list of organizations that the user has access to see.
Can this be done by including the list as properties of the Claim, or can it be done in any other way?
If so, how can I set up this Claim in ADFS?
The easiest way is to create a multi-valued attribute in AD for each user that contains the list of organizations.
Then have a normal AD mapping claim rule.
Note that this will not produce a list in one claim, rather multiple claims.
Refer: ADFS : Multi-valued attributes from AD.
The other way is to have each organization as a security group and then make the users membersOf each group as appropriate.
You can then create a group claim rule.
Refer: ADFS : Sending groups as claims.
Our chain goes:
ASP.NET app with WIF -> ADFS -> and maybe Azure ACS -> Facebook, Google etc.
We have users configured in AD with roles etc. These users can log-on to AD via ADFS and get their roles as per normal.
Optionally, they can log-on to one of the ACS providers and we have a use case that stores the ACS provider's unique ID in AD. If they use more than one provider, we have more than one mapping.
So we can map the user who log ins in via ACS to their "real" identity in AD.
What we are battling with is how to deliver the full set of claims to the users who login via ACS? Typically, you just get a name, email address and unique id.
Is there a claim rule that can search AD using the unique ID? This rule would have to establish which provider they used in order to use the correct unique ID in AD.
I guess we could query AD from the application but that means we have to add the code to all such applications?
We could probably do the conversion in a custom STS as well?
Any ideas, good links, articles etc?
Your scenario might have less friction if your chain looked like this instead:
ASP.NET app with WIF -> Azure ACS -> (ADFS or Google or Facebook)
Is this a viable option?
ACS integrates best with ADFS when ADFS is acting as an identity provider rather than a relying party. Furthermore, in one hand ADFS will happily federate with external identity providers to grant access to users from foreign directories, but I don't think you can get ADFS to authenticate users from its own local AD directory using a token issued from ACS.
You can achieve this by creating a custom rule in ADFS using the Claim Rule Language in the Claims Provider Trust for ACS (see here and here for some language documentation).
But: I'm not sure if you can search the AD with the unique ID right away, as the param type used to query the AD isn't specified in the Claim Rule Language. The rule templates use the windows account name (layout: DOMAIN\USERNAME) to search, thus I'd recommend using a (custom) attribute store instead of AD itself and map the unique ID to a windows account name.
Assuming you have your attribute store set up, you can create custom rules that set the windows account name claim and enables you to query AD with the template rules of ADFS.
The custom rule would look something like this:
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"]
=> add(store = "YourAttributeStore",
types = ("http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"),
query = "{0}", param = c.Value);
To really enable the template rules you also need to set the issuer on the newly generated claim, because they check if it comes from "AD AUTHORITY". I don't know if this is a legit approach but I do this for convenience. This requires a second rule that will look something like this:
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]
=> issue(Issuer = "AD AUTHORITY", OriginalIssuer = "AD AUTHORITY",
Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname",
Value = c.Value);
Regarding the distinction of different unique ID providers, it's your choice on how to handle it. You could create a custom rule for every provider, let the attribute store make the distinction or make generic queries to your attribute store. The documentation of the Claim Rule Language should help you here.
Note: This seems to be a topic commonly avoided in books about ADFS/WIF/Claims based Identity. This is my personal solution and it may not be best practice, it's just the most convenient I came up with. If anyone knows coverage of this particular topic: please share.
Also note: rule order matters in ADFS, the claim(s) created in the first rule are available in the following rules and so on, this is what makes this possible.
Edit: didn't see this Question was asked one year ago ... hope this answer is helpful to someone anyway.