Impersonation using JWT - asp.net

I am trying to implement JWT authorization based on this article.
I also need to let specific users (admins) impersonate other users (clients).
I see two possibilities here:
make admin requests using the admin token and add the impersonated client_id to each of the request;
request a new token for the admin which will contain the username and roles of the CLIENT in its payload, so it will basically become a client token, but it will also have two extra fields: "impersonated=true" and "impersonator_admin_id=x".
I would prefer the second one as it would be easier to use the .net built-in authorization attribute with the clients roles.
But I'm not sure if this opens up security holes or if it can be actually implemented using .Net's OAuthAuthorizationServer.

From your links, first decide if the admin is impersonating an user or acting on behalf of. Note that on-behalf-of != impersonation
A acts on behalf of B when A maintain its own identity and is given all rights from B
A impersonates B when for all intents and purposes A is B
In JWT RFC is not defined any specific claim for this purpose. In this draft the author proposes to include an on-behalf-of claim obo
{"obo": {
"prn":"mailto:joe#example.com",
"ctx":["urn:adatum.com:calendar"]
}}
prn identifies the principal for whom the bearer of the JWT is acting on behalf of.
ctx stablish permission contexts in which the bearer is allowed to act on behalf of the principal. This claim should by mandatory to restrict the contexts in which the delegated rights are to be exercised
Note that the obo claims are not included in IANA's JSON Web Token Claims, so they should be taken as a recommendation. There is a similar claim azp in OpenID but it is not clear how to apply it
azp : Authorized party - the party to which the ID Token was issued
Answering your question, in the first case I think you are talking about acting on-behalf-of, so include the client_id and the security context. The second case would be impersonation.

Impersonation always comes with serious security implications as it allows "to become someone else".
For that reason, you would need to make sure to make this state as visible as possible by e.g. introducing intensive audit logging. Also (to distinguish between real logins and impersonation logins) you would want to be able to transfer information about this very special state within your JWT access tokens by e.g. adding additional impersonated and impersonator properties to the profile of the impersonated user (as you described in your second point).
In the end you would probably end up having an regular API endpoint excepting requests like this ...
POST https://YOUR_DOMAIN/users/{user_id}/impersonate
Content-Type: 'application/json'
Authorization: 'Bearer {ACCESS_TOKEN}'
{
impersonator_id: "IMPERSONATOR_ID"
}
... which would hand out specific impersonation tokens that would allow to use service "through the users eyes".

Related

How do I structure authentication with a social IdP?

My system works as follows;
I have an ASP.Net RESTful API server, which contains a user database.
I also have a Xamarin.Forms application, with a registration and login page.
What I want is to have the ability to authenticate a login using a social IdP, and then, if that user has not been logged in before, register that user in my local database.
I have been reading up on how to implement OAuth 2.0 with OpenID Connect to authenticate my users with a social IdP, however, I cannot seem to wrap my head arround it. From what I've read, I shouldn't use an Access token for authentication, since that i what the ID token is for, however, I have also read that the only intended purpose for an ID token, is the client.
My problem then is, how can I make sure that calls made to my ASP.Net server, has been made by "real person", and how do I determine who makes the call?
Access token will be used determine whether the client application was authorized by a user to access a resource. The concept of ID token comes from OpenID Connect. Main purpose of the ID token is to authenticate the user to the client application (i.e. letting the client application know that the person who authorized the access is a valid person).
To do this, you have to validate the ID token. This can be done using third party libraries such as nimbusds or auth0. You can validate the signature of the token verify the integrity of the token and check the claims included in the token (by comparing them with expected values) to verify the user details. Also, you can add custom claims (any claim that is specific for your application/implementation) to the tokens through your identity provider so that you'll be able to validate those particular claims in order to verify the user.

Replacing Google Sign-In for Websites with Cloud Identity-Aware Proxy

There's an open feature request for Metabase to support IAP. I took a stab at it, and have a Clojure implementation of the steps detailed in Securing your app with signed headers (i.e. verify token header, verify token payload, retrieve user identity).
But this question isn't necessarily specific to Metabase. The general idea is to replace Google Sign-In and only use only IAP signed headers for authentication and user creation in an application on Google App Engine (specifically, GAE flex environment).
The "problem" is that the user identity information from the IAP token looks like: {"email":"alice#example.com","sub":"accounts.google.com:118133858486581853996"}. I also came across Using special URLs, but this returns something like: {"email":"accounts.google.com:USER_EMAIL","sub":"accounts.google.com:118133858486581853996"}.
With a Google Sign-In token, I can obtain values for given_name and family_name along with email, which means I can fetch-or-create a valid Metabase user. Is there a way to get the first and last name via the JWT sub, (i.e. accounts.google.com:118133858486581853996)?
Hm, if they have a public profile you can pass the number after "accounts.google.com:" to https://developers.google.com/+/web/api/rest/latest/people/get . Unfortunately, you won't be able to authenticate to that API as the user, since IAP doesn't currently provide a way to call let users delegate access to call Google APIs. (You'll have to use a service account to call that API.)
The other solution would be, if IAP provided a way to a) specify additional scopes in its OAuth request to Google, and if it then b) passed additional claims from the OIDC token into the IAP JWT, you'd be able to configure IAP to request the "profile" scope. However, IAP currently only requests the "email" and "openid" scopes, and doesn't have a mechanism for specifying additional scopes.
-- Matthew, Google Cloud IAP engineering

Track OAuth 2 provider on client page

I have the ability to login via Facebook and Google on my website. This is done using OAuth2.
I use the same redirect URL whether the user is returning from facebook or google, and pass through the provider name in the state field. Is this the recommended way to track the provider? Otherwise I do not know who to validate the token with if I do not know which provider the token comes from.
Are there other preferred methods for accomplishing this?
The state parameter should be an opaque value that cannot be guessed by an attacker since it is not protected from modifications. If you need to track state, you should refer to it by using the state parameter but that parameter itself should be randomized and/or encrypted. Storing the provider identifier in plaintext in the state parameter is not safe. Users could modify the state parameter themselves or attackers could craft an authorization request with a state value that they choose.
The way to track the provider is by storing it in the backend session state and generate a reference to that session/state that you pass in the state parameter. To prevent cross-site request forgery you should also keep some encrypted/randomized cookie that binds the state to the browser. This is described in more detail: https://www.rfc-editor.org/rfc/rfc6749#section-10.12
Addendum:
One of the problems with using OAuth 2.0 + provider specific extensions for login is exactly this: you cannot establish the provider and user identity in a way that works for all providers in a uniform and generic way. In your case you'll already have to know the provider before you can perform a sensible interaction with it. Enter OpenID Connect: it is a extension profile of OAuth 2.0 that gives you login semantics in a standardized way. It would give you a verifiable JSON object (JWT) with standardized values that tell you who the provider is (iss) and who the user is (sub).
Google signin already has migrated already to OpenID Connect, as has Microsoft and others like Salesforce, hopefully Facebook will follow.

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"));

OAuth access token and refresh token creation

I'm implementing my own OAuth authentication system (with refresh_token support) for an app and I have some questions about how to do it:
Client identification: The client is registered in the auth server and gets a client_id and a client_secret. How do I generate it? is there some kind of relation between both values?.
User authentication: The client sends the users_credentials (username+password for example) + client_id and gets a refresh_token and (temp?)access_token. That access_token is the one I should use in further request or I should use a accesss_token`=F(refresh_token,access_token,client_secret). In the second case what does the F function consist on?
Access token refresh: The client send client_id, refresh_token and gets a access_token (and a optional new refresh_token). Does the access_token need the same conversion (whatever it be), as in the point 2?
If I'm wrong, when and how is the client_secret used?
Complete answers and concrete examples will be "bountied".
The authorisation/authentication server generates these values when you create an account with them (for instance when you create a developer account with Facebook or Google). If you are doing these parts yourself, they should be cryptographically secure pseudo-random numbers or letters. Remember that the client ID is usually publically visible, so choose a reasonably large set of alpha-numerics (I use 30 characters). The secret is private and can be harder to guess so I chose 30 digits with letters, numbers and symbols. These are not related to each other, it is just that one is public and the other isn't.
The usual way this works is that there is a browser redirect to the auth server passing the client id in the URL (and redirect uri) and specifically NOT the user id and password. The whole point of OAuth2 is that the client system never sees the user name and password, only the auth server. After this redirect, the auth server verifies the client id, checks the username/password (for instance) and then returns to the redirect uri with a temporary code. This temporary code is passed back to the Auth server in order to obtain an access token. Since this call is made as a POST from the server, it also passes the client secret to verify that it really is the correct client system and not someone who stole the client id from somewhere else. At this point, the auth server will return an access token (and optional refresh token - you do not need to use them, I don't).
If the client system wants to log the user in without them having to type in their username and password all the time, it can use a refresh token, if available, to call back onto the Auth server and if the Auth server is happy that the refresh token is still valid and any other business rules are correct, it can give you back another access token directly without the user being involved.
I recommend reading the OAuth2 spec here: OAuth2 Spec RFC6749. It can take a while but if you delete the bits you don't need and reduce the amount of data, there are plenty of useful examples in it.
FIRSTLY, The client identifier can be any string that you want, but it should be unique for each client. It can even be the client's choice if you wish.
The client secret should be a cryptographically strong random string. Here is how you could generate one in C#:
RandomNumberGenerator cryptoRandomDataGenerator = new RNGCryptoServiceProvider();
byte[] buffer = new byte[length];
cryptoRandomDataGenerator.GetBytes(buffer);
string uniq = Convert.ToBase64String(buffer);
return uniq;
SECONDLY, The whole point of OAuth is to allow external apps to do things on your behalf without asking for your credentials. So, you need to implement an authentication server that does the logging in part for you. The user opens the app and gets an option to Log in using your website. You tend out access tokens and refresh tokens once the user has keyed in his credentials. The app can then simply use the tokens to perform actions on the user's behalf. I wrote an answer to How would an efficient OAuth2.0 server / provider work? that explains how access tokens can be constructed.
Remember, the need for refresh tokens and the lifetime of access tokens purely depends on how you intend to use them and what does your security framework look like.
LASTLY, The refresh token can also be an HMAC encoded string/a JSON object as I had explained in the answer to the linked question. You can have random refresh tokens and a large backend storage to keep it to verify the tokens in the incoming requests, or have HMAC encoded strings for added security/less storage requirements/latency to decrypt/encrypt tokens.
Also, do make sure that you go through all the flows and possibly the RFC too as mentioned by Lukos.

Resources