How to extract application return URL and other custom parameters in AD FS 2.0 claim rules? - rules

This is probably a very basic question about AD FS 2.0 claim rule design that I haven't found an answer to (newbie). I'm probably missing something very basic, but here goes.
I'm deploying a federation within a company. The company users will be able to browse to a web application A, B, C etc. Each app will have their own subdomain URL, e.g. app-a.company.org, app-b.company.org, etc. When the application redirects to its trusted STS landing page I want the return URL to be passed to the STS. In the STS claim rules I want to extract that return URL and perform a database lookup, e.g. for the current user and the application with URL "app-a.company.org" I want all roles that the user has in that application (e.g. admin, superuser, purchaser, whatever).
My questions are:
How do I pass along the return URL to the STS?
How do I write the claim rule? (I know how to make the database lookup and issue the results, but I don't know how to retrieve the return URL or any other custom parameter for that matter in a claim rule).
Cheers,
Linus

Now that I know a bit more I'm going to answer my own questions. Mostly this issue seems to be a confusion over terminology.
I was under the impression that I needed to create a global rule for all applications in the STS. This is not the case. Instead, it is possible to write rules for separate applications (these applications are known as Relying Party Trusts in AD FS terminology, i.e. an entity that trusts whatever claims the STS issues). The relation between the STS and the application is 1:1.
In my case I needed the app domain to serve as the unique identifier because I needed to query a database (aka Attribute Store) at a later point to get more attributes. Since application specific rules can be written and the relation between the STS and the app is 1:1, I simply created a rule with the domain name hardcoded.
So to answer my numbered questions above:
No need to pass it along to the STS since the Relying Party Trust relation serves as the permanent connection between the two.
Hardcode a simple unconditional issuance (or add) claim rule, i.e. => issue(type = "http://myclaims/appdomain", value = "app-a.company.org")

Related

ASP NET CORE DDD - CurrentUserService in Domain layer

I am working on a school project which basically acts like a Messenger with Events etc.
Recently I came across DDD and I decided to try to implement it's concepts in my project.
I ran into a problem, where each time I want to edit an entity I need to check, if a currently logged user has rights for it.
I have CommmunicationChannel entity (AR) which has ICollection<CommunicationChannelMessage>. When I want to edit message I need to load CommunicationChannel entity, find CommunicationChannelMessage in it and then check if currently logged user is the author of the message.
I decided to create DomainService MessageManager, which has method Update(CommunicationChannel channel, string messageId, string newContent).
This method loads the message or throws NotFoundException, after that it check, if user has right to it and if not throws ForbiddenAccessException.
Basically, domain layer now has a responsibility to check if currently logged user has rights to do something. The idea behind this is that there will be no place in code, where I can forget to check permissions of the user. I can only call methods from this manager and they check permissions everytime.
So my question is following. Can a domain service have a reference to ICurrentUserService (returns entity of currently logged user). Shouldn't the check of user permission be application specific concern in Application layer instead of domain layer?
Thank you so much for your answer.
Stricto sensu DDD does not states anything regarding application layering, besides :
domain layer must use object modeling
domain layer is where business rules are implemented
Now the problem must also be split in two different security concepts : authentication (find user identity) and authorization (is user allowed). Authentication is always an application cross cutting concern, usually handled by an asp.net middleware like Kerberos, OIDC, etc ...
You have two approaches possible for your authorization problem : consider the identity verification as a business requirement or a security cross cutting concern.
In case of a business requirement, author must exist in the domain model, at least as a login/username property on message. Add a parameter to your Update() method for actual user identity to be compared with message author. Your controller can pass the user identity from asp net core authentication or any external auth service if a conversion is required.
If you want to make that a cross cutting concern, you don't need to model message author (unless useful for another business requirement). Make a custom middleware, or insert a security layer somewhere in your architecture (a more precise answer would require insights on your actual architecture).

Differences between audience, issuer, and client terms in JWT, OAuth and OIDC

"The half of knowledge is to say I don't know when you don't" proverb
Every time I try to keep my knowledge about these terms clear and correct. However, over the development of new projects and acquiring new knowledge (SaaS, Multi-tenancy, 2Step Verification, IdPs, SSO ), I feel like I still do not understand them correctly. Any one can give a simple and efficient explanation?
I am an ASP.NET developer.
I like that quote, so, this is some answer. Let's say we have a jwt like this
{
// ...Some other claim
iss: "MyKnowledgeCenter.com",
aud: "Abu.questioning.com",
// ...Some more other claims
}
First thing is abount issuer, which represent as iss. This indicate that where the whole Jwt you have come from. For ex: We have a request for access token at https://abu.Identity.com, but the issuer could be MyKnowledgeCenter.com, or https://abu.Identity.com or anything else. We have freedom to just indicate those as we code the identity centralize server ourself.
In short, iss is just a Jwt claim that have nothing difference from other, except it's meaning is to indicate that this jwt was self-declared that it came from an issuer that called MyKnowledgeCenter.com from this example.
About audience, again, it's just a claim in Jwt, that was intended to set as we wish, represented for one or a collection of which services that the Jwt itself intended to use for.
I love example: I have 2 microservices is Catalog and UserProfile, that require client to have a Jwt was issued at MyKnowledgeCenter.com to access their resources. If on those 2, validating on audience is required (as we can set it), then, even if the sign is valid, but aud was lack of Catalog, client cannot access Catalog microservice resources. The same applied for all others.
Okay, so where's the client ?
Well, that's indicate something as setting but not re-presented in the Jwt.
Imagine, we have a centralize authentication server, but we only intend to serve our own services, and clients. Not the whole Internet world, right ?
So, specifying those specific clients would benefit, as I just want to serve an app on iOs, another from android word and a website of our own. Therefore, 3 clients. If any request that came from any other clients that have informations doesn't match one of those 3, we rejected them immediately.
Simple enough ?

What's the practical workflow using claims for authentication and authorization in a web application?

I just don't still get Claim Based Authentication/Authorization workflow.
The application allows authentication via Facebook.com
After the user is authenticated, an admin can give her/him a claim of having the role of Manager, which creates another claim (where?)
Of course, this claim won't be on the facebook.com server, question 1: where should that claim be stored?
When the user log in again later, I get the claim of facebook.com and I should get the claim from the application. and merge them?
How is the workflow? Trying to understand claims in practical usage.
Basically, Facebook tells me that I'm john#doe.com, and 'field in the blanks' adds a claim that I'm also a manager of domain.com
then I pass those claims to domain.com?
How should I configure in asp.net the application at domain.com to trust Facebook and 'filled in the blank piece' and request claims from both?
I guess I'm using external providers for Authentication and my own provider for Authorization, how this is created on ASP.NET (web API / MVC)?
UPDATE (for clarification)
Let's get backwards. I create a web application where users can register.
'Somehow' there's an trusted ClaimsBased authority somewhere (this should be another application??) where I request the claims for a particular user to see if have particular rights on my application.
So I imagine something like :
/authserver/claims
and my validation checks if X claim is met to do certain operations.
later I add to Facebook. now I have
/facebook/claims
which tells me the user is X
and
/authserver/claims to see if can do operation X on resource Y.
how this is managed on ASP.NET? and where my own claims should be created/exposed/developed.
I think I'm missing something fundamental here.
I think the important thing to understand is the difference between authentication and authorization.
Authentication - the act of confirming the truth of an attribute of a datum or entity.
Authorization - the function of specifying access rights to resources, which is related to information security and computer security in general and to access control in particular.
So, typically for secured system, the workflow starts with Authentication. When a user first connects/uses a system, then are not authenticated (lets say this user is of a type/group Anonymous). The act of the system determining the user is not authenticated is an Authentication in and of it self. Based on being Anonymous, then the act of the system determining what that type of user anonymous has access too is now authorizing what the user can do. For very secure system, the only access anonymous has is to the login screen/page. Once logged in the user is assigned a unique identity and assigned some type of group policy/role (if not already created).
with a web-based application and having a website (#1) authenticate for another website(#2) it becomes a bit more complicated. When I log into StackOverflow(#1), I use my Gmail(#2) account. I get redirected to Google with some special way for Google to know that the page I came from/to go back to. This could be a special key/url combination or for less restrictive access, usually has to do with return url (after I say, yes, where I go back too). Google will create a special authentication token that is specific to the url I am returning to. It is tied to the URL because that means that my token on StackOverflow won't allow me or anyone else to log into say NewEgg for example (in other words someone at StackOverflow with access to the database can't use my token to authenticate as me on some other website, but technically they could log in as me on StackOverflow, but they own the website, so that doesn't really matter). Now I am authenticated on StackOverflow (but technically StackOverflow doesn't even need to know any information about me, just my Token).
On StackOverflow as a new user, a new account is created. This account probably has a one to many relationship to my unique account on Stack Overflow and multiple of logins (and type of logins, OAuth, OpenID or SO Login). Once the account is created, I have whatever access they have setup by default. If I need more or some trigger (lets say based on my Reputation points :) I now have access to Administrative functionality (given some role). That role is tied to my account and indirectly tied to my authentication. This means that I can create additional logins (say a Local SO Login) but keep my Account.
As for each Authentication resource (Google, Facebook, etc) there will be difference schemes for Authentication, but there will always be at least a token (or more than one token) for a website to say who I am (in a generic way).
So website #1 (Stack Overflow) has requested website #2 (Google) to Authenticate me. But only website #1 knows what am I Authorized for.
For role specific functionality, there are a good number of answer on SO dealing with ASP.Net Identity and the Role Manager:
Creating Roles in Asp.net Identity MVC 5
mvc 5 check user role
A much more Indepth look into Identity with MVC - Extending Identity Accounts and Implementing Role-Based Authentication in ASP.NET MVC 5
If you're using ASPNET.Identity (http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity), you can add a Role claim type to the user. It'll be associated with the userlogin, so when the user authenticates with Facebook, these user claims will be added and available in MVC.
See the following code fragment:
var acRes = await UserManager.AddClaimAsync(userId, new Claim(ClaimTypes.Role, "MyRole"));

Purpose of ProviderUserName column in DotNetOpenAuth sample

I've started an ASP.NET web site in Visual Studio using a Microsoft pre-defined template. This is to help me learn about OpenID within ASP.NET.
Inside the included SQL database within the sample site, there is a table called UsersOpenAuthAccounts that contains a column called ProviderUserName.
Can anyone tell me the purpose of this column? In my tests, this seems to store the username that I would log into an OpenID site with (e.g. my Google username - my email address). However, I also see that the ProviderUserId column holds the IAuthenticationResponse.ClaimedIdentifier value, e.g.
https://www.google.com/accounts/o8/id?id=AIt................g3c
...which would be used to identify the user against the OpenID provider for future requests.
Therefore, is there any point in including the ProviderUserName column? It's not actually used anywhere else within Microsoft's sample site.
ProviderUserName is... a bad idea (IMO).
The OpenID Claimed Identifier is the right string to check for return users. It reduces security to use anything else, including email address. If you're only interested in OpenID logins then you may want to just throw out the ASP.NET provided code and use DotNetOpenAuth's OpenIdRelyingParty directly and deal with the users table yourself. It will be about as simple as your current code, but without the unnecessary columns.
What the ASP.NET team's additional column and façade classes give you is the ability to mix OpenID logins with OAuth logins, which allow you to accept Twitter and Facebook accounts at your site as well. OAuth wasn't designed to be an authentication protocol, so those who use it have to make up their own idea of a username. In order for that to be globally unique, it must be prefixed by the provider who is issuing that username. So you have ProviderName ("twitter" or "google") and a ProviderUsername which is the username (or user id perhaps) of the account from the OAuth service provider.

Handling Nested Group Permisions (ASP.NET Role Provider)

We have a security module which, based on group/role membership, controls permissions to resources in ASP.Net. I've built a custom ASP.Net Role Provider that queries Active Directory for group membership and which is used by this module.
Security checking works as follows for each request (caching used in places for performance reasons but excluded from this list):
Query AD for list of users group memberships
Query database for a list of users and groups with access to the requested resource
Compare results from AD with results from the database. If the user explicitly has rights or if a group that the user is in has rights then allow access, else don't.
The problem arises when we have nested groups. Lets say we have two groups: ParentGroup and ChildGroup, where ChildGroup is a member of ParentGroup in Active Directory and where our user is a member of ChildGroup. According to the logic above if we give ChildGroup access to a resource then then the user can access the resource too.
Now logically (to me anyways) if we give ParentGroup access to a resource then all members of it, and any sub groups and their members acquired recursively, should also be able to access said resource. But instead, because of the way my logic works they can't access the resource. Step 1 from the above list does not see ParentGroup it only see's ChildGroup, and Step 2 only see's ParentGroup and does not see ChildGroup.
So the question is, to make it work how I described it "Logically" should, where should I fix the problem, and is there some method that would work better then another?
Try using the WindowsPrincipal.IsInRole() method instead of querying AD directly. I posted some sample code over here which might help.

Resources