Getting ADFS claims from AD when user logs in via Azure ACS - wif

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.

Related

How to secure an API with OIDC/OAuth

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.

Restrict client access in a single realm with keycloak

I have a single realm with 3 single-page applications and a shared backend. I want to restrict the access to one of the SPAs so that users without a specific role can't log in.
But once you create a user in the realm, he can log in to every SPA client. I can restrict the endpoints of the backend but I don't want to programmatically reject the user in the specific SPA but automatically on the login page.
I tried to use client roles which don't seem to have an effect in this case. The only solution I have found so far is to create separate realms which I think is conceptually the correct way but unfortunately brings up some practical issues, e.g. the administrators of one realm must be able to manage (CRUD) users of another realm which seems fairly unintuitive.
users without a specific role can't log in - it isn't good requirement. How system will known if user has a specific role without log in (authentication)? Keycloak provides Open ID Connect SSO protocol, which is designated for authentication. After successful OIDC authentication is token generated, which may contains also user role. So only then authorization can be applied. So let's change requirement to: users without a specific role can't access SPA, which better fits into OIDC concept.
The mature OIDC SPA libraries offer authorization guard (name can differs, it is some kind of post login function), where authorization can be implemented. Authorization requires to have a specific role in the token usually, otherwise user is redirected to the custom route, e.g./unauthorized. That's the page, where you can say a reason for denying access. Common use case is also customization of the app based on the user roles. For example users with admin role will see more items in the menu than standard users - that's also kind of authorization. Random example of SPA library with authorization guard (I'm not saying that's a best implementation) - https://github.com/damienbod/angular-auth-oidc-client/issues/441
Keep in mind that SPA is not "secure" - user may tamper code/data in the browser, so in theory user may skip any authorization in the browser. He may get access to SPA, so it's is important to have proper authorization also on the backend (API) side. Attacker may have an access to SPA, but it will be useless if API denies his requests.
BTW: You can find hackish advices on the internet how to add authorization to the Keycloak client with custom scripting (e.g. custom scripted mapper, which will test role presence). That is terrible architecture approach - it is solving authorization in the authentication process. It won't be clear why user can't log in - if it is because credentials are wrong or because something requires some role in the authentication process.
You should indeed not create multiple realms, since that is besides the point of SSO systems. Two approaches are possible in your - presumably - OAuth 2.0 based setup:
restrict access at the so-called Resource Server i.e your backend
use a per-SPA "scope" for each SPA that is sent in the authentication request
The first is architecturally sound but perhaps less preferred in some use cases as you seem to indicate. The second approach is something that OAuth 2.0 scopes were designed for. However, due to the nature of SPAs it is considered less secure since easier to spoof.
I was able to restrict users access to application using following approach:
I've created to clients in my default realm (master) i called my clients test_client1 and test_client2 both of them are OIDC clients with confidential access by secret
I've created a role for each of them, i.e. i have role test_client1_login_role for test_client1 and test_client2_login_role for test_client2.
I've created a two users - user1 and user2 and assign them to client 1 and client2 role. But to restrict access to client1 i have to delete default roles:
That did the trick, when i am logging with user2 i see test_client2 and not test_client1 as available application:
But i did n't delete roles from user1 and therefore i could see both clients when i am log in with user1:
Therefore you should use different clients for your applications, assign to each of a client specific role and remove from users default roles and add one releted to specific application.

OAuth Apps on a Single Domain

My company has a website. Let's pretend that it's hosted at http://www.example.com. I have three apps that I need to build for different teams. Users will have different permissions, possibly different OAuth logins, per app. I'd like to host apps on domains like:
http://www.example.com/apps/my-first-app
http://www.example.com/apps/my-second-app
http://www.example.com/apps/my-third-app
My question is can I do this? I'm trying to understand if OAuth tokens are per domain or per app/url. Thank you for your help.
OAuth Tokens are indeed per domain / app / url.
I did read a while back you can create multiple tokens and store those in the db for the time being so that multiple users with multiple roles can use those tokens to do the things they are permitted to in one domain for instance. I cannot really remember where I read it, but once I do i'll get back to you as soon as possible
You should be able to have multiple consumer apps like that. I'm not sure providers would work however.
Each consumer has a unique client ID and secret (and usually a callback url on the provider, github say). As long as each consumer application has a unique client ID I can't see why this wouldn't work - just create 3 applications on the provider and then make you set the callback urls correctly.

How to implement mutli-tenant login with Facebook, Twitter, Google+, etc?

I want to allow users of a SaaS based, asp.net MVC, Multi-tenant DB to login using their social media credentials (FB, TW, G+, etc).
In addition to the social media account validation, how can we determine which tenant or users within a tenant in the DB to validate against? I presume some flavor of Asp.Net Identity should be used to bridge the gap??
I have implemented a custom OAuth server that inturn handles the pluggability of the various social media login modes via OWIN middlewares.
However, when you wanted to have a simplified approach, you can choose to go with Windows Azure Access Control service which can enable you to identify the tenant via their URI.
In that case, you can infer the tenant name or tenant unique value from the URI [like a subdomain part] of the URI.Host.
You may refer here / here / here.
In case you wanted to build your own model, you will have to capture the tenant information via either a unique URI from where the tenant comes from or from getting a tenant unique value from the UI or as a query string from a URI [Rare & least secure case].
The points worth pondering upon will be
Time
Cost [Azure does not come for free]
Customization aspects
Please share your thoughts on the points above.

How can I get roles from AD with MVC Azure AD Authentication?

I setup and MVC 4 application and added authentication against our Azure AD server as outlined here: http://msdn.microsoft.com/en-us/library/windowsazure/dn151790.aspx
Authentication works as expected. However, I'm not getting any roles back by default. There should be several AD groups created and I would like to use them to role restrict the application via the [Authorize] attribute in MVC.
I can't really find a good place to even start figuring this out. Can anyone give me an outline or point me to a good tutorial?
I should mention that I'm not the administrator for our Azure account, so I need to be able to tell our admin what to do if any setup is required on that side.
First, tokens returned by Azure AD do not currently contain claims for roles or groups, so you need to get them from the Graph API. Second, roles in Azure AD that are returned by the Graph API are not necessarily intended for use in an ISV/LoB app, and in general you should use security groups for authorization instead. To perform authorization, you should use the checkMemberGroups or getMemberGroups operations in the Graph API, which are transitive and valid for this purpose.
If you check out the following resources in order, I think your questions will be answered. You'll learn how to authenticate to the Graph, call it, and configure your application to use the result of the group operations to perform authorization:
Using the Graph API to Query Windows Azure AD -- This is the second walkthrough to complete now that you've done the web SSO one.
Authorization with Windows Azure Active Directory
MVC Sample App for Azure AD Graph
Blog post describing checkMemberGroups and getMemberGroups
How do I get role and group membership claims for users signing in via Windows Azure AD? -- This one is out of date in regards to the methodology for authentication and the UI for managing users/groups, but it's still useful. Pay special attention to the section on the custom ClaimsAuthenticationManager, which gives you an idea of how to inject role/group data into the ClaimsPrincipal object early so that it can be used in the [Authorize] attribute or other authorization logic.
Sean answer is a bit outdated. You can now configure Azure AD so it will include groups or roles inside JWT token so it will be included into ClaimsPrincipal.Current.Claims so standard [Authorize(Roles = "yourRoleName")] attribute will work.
Here is introduction post. Which basically says you have two options:
Use groups claim - you need to change groupMembershipClaims value in app manifest and later in application you can check for ClaimsPrincipal.Current.FindFirst("groups").Value to see in what group user is (you only get group id). You can write you own Authorize attribute that use this. more info
Define roles for you application and then use normal code for testing if user is in role:
[PrincipalPermission(SecurityAction.Demand, Role = “yourRoleName”)]
[Authorize(Roles = “yourRoleName”)]
if (ClaimsPrincipal.Current.IsInRole(“yourRoleName”)) { //do something }
You need to edit roles in you app's manifest.
More info here and here. Values needed to be set in manifest are described here
What is really strange is that you can't assign more than one role to group from Azure web page. You need to use azure graph api for this.
If you can't see Users and Groups tab in Azure portal you probably need Azure AD Basic or Premium edition. If you are working on free azure subscription you can use free Azure AD Premium trial to test stuff.

Resources