Access token and user ID - oauth-2.0

I'm currently trying to authenticate an angular 7 app with ADFS 2016 (using angular-oauth2-oidc). So far, it works pretty well. When I access the application, I'm redirected to ADFS login page where I enter my credentials and gets tokens.
Now, when the app calls the a web API, it send the access token in the request headers. The access token returned by ADFS looks like this:
{
"aud": "microsoft:identityserver:xxx",
"iss": "http://xxx/adfs/services/trust",
"iat": 1554561406,
"nbf": 1554561406,
"exp": 1554565006,
"apptype": "Public",
"appid": "xxx",
"authmethod": "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
"auth_time": "2019-04-06T12:21:39.222Z",
"ver": "1.0",
"scp": "profile openid"
}
The issue is that the web API must know the ID of the user making the call (as there are some permissions defined at application level). I saw here that I can add claims to the access token, which I did. However, when reading articles on Internet, I read that apparently the access token is not supposed to be used to identify the user, so I don't know if it's correct to add a claim used by the web API to identify the user.
However, I read here that
The only user information the Access Token possesses is the user ID,
located in the sub claim.
But by default, ADFS does not provide a "sub" token. Is it correct if I add a "sub" claim by myself that contains the email address of the user or do I have to proceed in a different way?

Yes, access token is not supposed to be used to identify the user. But if you can get a user identifier into the access token and it's all you need to know about a user, then it's probably the easiest way. But it's implementation-specific for your auth server.
The standard way is to ask for the profile scope (which you did) and get information from the userinfo endpoint (see OpenID Connect RFC). If you use this way, you may want to cache the response, so you don't need to make this HTTP call on every client request.
If your backend API is used just by the Angular application and is not supposed to be called by third parties, you could also consider using the backend as the OAuth2 client which receives an authorization code and exchanges it for an ID token. Then, it can save the user's identity (read from the ID token) in a session and issue a cookie identifying the session. So there would be no need for the frontend to send a token on each request. This would make the backend stateful, but it might be easier to implement.

Related

How to authenticate mobile app to web service using Azure AD?

Currently I have this setup:
At login, and in every subsequent request after login, a mobile application that I have built uses Basic Authentication to authenticate the user with a web service that serves the app with information it requests.
On every request the Authorization header is inspected, the password and username are extracted from the header, the password is hashed using a proprietary DLL (so the web service doesn't actually contain the hashing algorithm) and compared to the hashed password associated with the username that is stored in the database.
I have now been asked to include Azure AD SSO in the login options.
After reading much about the topic, this looks seems to me like the setup:
I'm curious about a few things:
Is this setup correct, more or less?
Does the app send the Identity Token to the web service? If so, how does the webservice validate that token?
Is it correct that the webservice can match the Azure Identity to the DB user using one of the claims in the Security Token?
Where do Access Token fit in this picture?
Thanks for the help!
(Side Note: I know that Basic Authentication is not the preferred way to go in the first scenario. This was a temporary decision till we developed the token handling code, it only works using HTTPS and this is an internal application - you wouldn't be able to activate the app unless you have a code we give you)
I have little experience in azure ad but I think we could talk about your case.
First, whatever id token and access token are both jwt token, so to your web service application, you need to use jwt decode library to decrypt the token and get claims it contains. Here we need to know the difference between id token and access token, and I think you'll know that for your web service application, if it's more likely to play the role of an api application, you need to use access token because this token also contains user information. Then you need to add code in your program to decode the token and check if it's a 'valid' token for the request.(Because you've used azure ad to achieve the login part, you don't need to use your custom login part.)
Next, the signing in feature provided by azure ad requires to use account and password in the tenant which azure ad belongs to, the user accounts may look like xx#xx.onmicrosoft.com, it doesn't required to keep sycn with the accounts in your database, so it's difficult and needless for you to compare the user name obtained from the decoded token with those in your database. Because when your web service received the token(id or access token), that means someone has passed the authentication from azure ad. The token contains user information including role, expired time etc. You need to check if the token has expired and if has the correct scope. (Let's see a common situation, microsoft provides many graph apis to call, when accessing these api, we need to provide access token in request head with matching scope, e.g. https://graph.microsoft.com/v1.0/me
requires a delegated api permission of User.Read)
To sum up here, if your web service just required the users in your database to sign in then can be access, id token and access token are both suitable for you because they both contains user name like 'xx#xx.onmicrosoft.com', what you need to do is decode the token and check if the token has expired and whether this user exists in your database(you may set up a mapping between them).

Is "Resource Owner Password Credentials" safe in OAuth2?

So, I'm developing an API using slim/slim and league/oauth2-server to manage the OAuth2 connection. OAuth2 will be useful because I will need to use Client Credentials grant between services.
Then, I'm also developing an hybrid app with React Native. This app will requires user login by using e-mail and password or connecting with another services (such as Facebook, Google, Twitter, etc).
And I'm confused about what OAuth2 flow to use for this case. Across the web are a lot of articles saying that Resource Owner Password Credentials is not safe anymore, and we should use instead Authentication Code with PKCE.
But I can't discover or understand how to apply Authentication Code with PKCE in a first party app, because all documentation talks about you will need the uses a browser to get authentication code in redirect_uri.
The flow I imagine is something like that:
User open the app, then insert your credentials username and password;
This screen will connect to API /request_token URI sending { 'grant_type': 'password', 'username': username, 'password': password, 'client_id': CLIENT_ID }, considering it as a public app we can't send client_secret;
The API validates credentials and returns some data such as { "access_token": access_token, "token_type": "JWT", "expires_in": LIFE_SPAN }, here we will use JWT to gerenate the access_token based in public/private key;
Authentication done, the app will store the access_token while it's alive and when it expires will do the flow to refresh_token.
My question: is it safe? Scott Brady did some "aggressive" article talking it's NEVER safe.
How apps does this things? When I use Instagram app, for example, they own the app and the API, I don't need a browser in the User Experience flow. Are modern apps using "Resource Owner Password Credentials" or "Authentication Code with PKCE"? There is a away to avoid insert browser in the flow while using "Authentication Code with PKCE"?
[EDIT] Possible Solution
As Gary Archer said "Auth Code flow with PKCE is recommended - along with logging on via the system browser", but we are not talking about grant permissions to access users data or third-party apps.
As a designer I don't agree that loggin in the first-party app owned by the same API owner requires a browser this is the not the User Experience we are looking for. And all apps we see such as Instagram, Facebook, Uber... we just put your username and password and we have access to your account.
What I will do is create a custom version of Authentication Code with PKCE removing the required_uri.
[EDIT:2] The New Flow
After a lot of search, I found some answers I think was interesting to adapt. As above, I removed redirect_url from flow. Look:
The flow starts in a login screen, when user give your credentials;
Client generates a code_verifier then hashes code_verifier to code_challenge and sends it to Authorization Server with following parameters:
response_type=code : indicates that your server expects to receive an authorization code.
client_id=xxxx : the client id.
client_integrity=xxxx : app integrity check for first-party app.
code_challenge=xxxx : the code challenge generated as previously described.
code_challenge_method=S256 : either plain or S256, depending on whether the challenge is the plain verifier string or the SHA256 hash of the string. If this parameter is omitted, the server will assume plain.
username=xxxx : username to authenticate.
password=xxxx : hashed version of password.
state=xxxx : a random string generated by your application (CSRF protection).
Authorization Server will validates user authentication, stores code_challenge and return the authorization_code with a client_token;
After receive the aauthorization_code and client_token, Client saves the client_token and immediately send authorization_code back to Authorization Server with following parameters:
grant_type=authorization_code : ndicates the grant type of this token request.
code=xxxx : the client will send the authorization code it obtained.
client_id=xxxx : the client id.
code_verifier=xxxx : the code verifier for the PKCE request, that the client originally generated before the authorization request.
Authorization Server will validates all data and, if everything is right, will return the access_token;
Client will set Authorization header with the access_token and always send client_token to every request, it will be only accepted with both values are right;
If access_token expires, then Client will do a request to refresh access_token and get a new one.
Now, I will reproduce this logic to PHP language. If everything goes right and I hope it does, I will be back with definitive answer.
[EDIT] Clarifications
I'm using OAuth2 to user connect with your third-party accounts (Google, Facebook, etc). But user also can log to a local account in my database. For this case, user doesn't need to grant anything at all. So, no makes sense send user to a browser to him does your login.
I wondering if, to this case, local accounts, we can use Resource Owner Password Credentials or it's more safe Authentication Code with PKCE (we already conclude it's a better approuch). But Authentication Code with PKCE requires redirect_uri, do I need uses this redirection to log users into a local account where they don't need to grant access?
Let's go then. After a lot research, I found some approaches that I will apply and may work correctly. So, first of all, here is the challenges:
You must never trust in clients running in client side. There's a lot of concerns about, your applications can be decomplied, modified, the users devices can be with a malware or connection may suffer with a man in the middle attacking (MITM)...
An API Server, even using OAuth2, will be able to only identify WHO is accessing the resources, but not WHAT is accessing. Therefore, any sensitive information will be dangerous, anything can steal it and uses it.
Resource Owner Password Credentials makes part of OAuth2 protocol for authorize resource owner to access your resources. So, it doesn't make part of authentication process and you will your ruin if you treat it like that;
By using ROPC grant type there is no way to know if resource owner is really making that request, what make "easy" a phishing attack. Reminds about "you know WHO and not WHAT". For last, this kind of grant makes easy for whatever thing assumes the user identity;
This grant type also goes against OAuth2 propourse, since OAuth seeks to avoid the password use to access resources. That why many people say to don't use it;
For reinforce, it's important to highlight ROPC is not authenticating user, but it just authorizing him to access the resource server.
And yes, ROPC allows for refresh tokens, but there are two issues: first, client needs resupply credentials each time needed to get a new token; second, if using a long-term access code, then things get more dangerous.
To prevent a malicious thing from arbitrarily using user credentials there are access tokens. They replace passwords and needed to be refreshed in short amount of time. That's why they are so much better than HTTP Basic Authentication.
That's why is recommended to use in modern apps the Authentication Code with PKCE, it provides all features and benefits of using OAuth2 protocol. But, here cames a long discussion and, even, problem for developer community:
To get an Authentication Code some user needs to make your login in a browser, grant access, redirect back to client and, soon, client will receive a code to exchange for an access token.
This scenario works good and NEEDS to be used for third-party apps. But, what if it is a first-party app? When you own the database with user data and you own the "trusted" app, redirect user doesn't make any sense. Right?
At this moment, my question is: how can I use the AuthCode (PKCE) flow without redirect user? And, again, it's important to highlight that talking about OAuth2 protocol is always the same that "to grant client to access resource server" (authorization, not authentication).
So the real question is: why Authorization Code needs a redirection at all? Then, I came with the following answer:
This flow requires to know client credentials and user consensus to turn back an authorization code.
That's why I was wrong in my edits. There's no change needed in OAuth2 protocol (sorry me for think different). For this reason, what OAuth2 needs is a authorization mediator, above your layer. Thus, the authorization code not will turn back to client, but to authorization mediator that, finally, will return it to client. Makes sense?
How it gonna work? Well, will be need 4 different "cores":
Authentication Server: will be responsible to authenticate user credentials and client identity. The main objective is to prove "WHO is the user and WHAT is connecting to get authentication";
Authorization Mediator (one layer above OAuth2): will validate client unique identity to ensure client/user is "know" and can get an access token;
Authorization Server: makes part of OAuth2 implementation, nothing change. Will authorize a client to get your authorization code, access tokens an refresh tokens;
Resource Server: will allow access resources through an access token.
And, then, security techniques we may consider:
API Key: each application (client) will have your own API Key with permissions scopes associated with those keys. By using it, you can gather basic statistics about API usage. Most API services use statistics to enforce rate limits per application to provide different tiers of service or reject suspiciously high frequency calling patterns;
Mutual SSL Authentication: by using this technique client and server exchange and verify each other's public keys. Once the keys are verified, the client and server negotiate a shared secret, a message authentication code (MAC) and encryption algorithms;
HMAC: API Key will be separeted into an ID and a shared secret. Then, as before, the ID is passed with each HTTP request, but the shared secret is used to sign, validates and/or encrypt the information in transit. The client and server will exchange the shared secret with algorithm such as HMAC SHA-256;
Protecting code application: using code obfuscators will make harder to locate and extract sensitive data from app, such as secret shared, api keys, public keys...
Handle user credentials: providing a simple method to user login and prove your identity. After insert valid credentials, server can return a user token (JWT) and emulates a user session with this.
Let's look at flow:
Part one: autheticating user and client;
User will type your credentials and be asked to prove your identity using your e-mail or mobile number, after Client will send user credentials (such as { email, mobile_number, hash ( password ), verification_method }) to Authentication Server route /login;
Authentication Server will validate user credentials and send a one-time password to user confirm your identity (for e-mail or mobile number as choose by user);
Then, user will insert the OTP received and client will send back to Authentication Server route /login-otp including the verification method (such as { otp, verification_method });
At the end, Authentication Server will return a { hash ( shared_secret ) } to be used soon.
Part two: authorizing API access;
When receive shared_secret Client will stores securely at mobile app, then it will ask for a authorization code using PKCE calling /auth with { response_type, client_id, scope, state, code_challenge, code_challenge_method }, Authorization Server will validate credentials and return an authorization code with no redirects;
Later, Client will exchange received code to an access token accessing /token, but it will need to send some extra data: { payload: { grant_type, code, client_id, code_verifier }, timestamp, hash ( some_user_data + timestamp + shared_secret ) };
Authorization Mediator will receive this request and validate trying to generate the same hash generated by user. And redirect all data to Authorization Server that will validate client_id, code and code_verifier responding with an access token;
This new access_token will return to Authorization Mediator and, after, to client granting access to API resources.
Part three: accessing resource server;
Client will each time needs send a call to API /api containing the Authorization header and some extradata with { timestamp, hash ( some_user_data + timestamp + shared_secret ) };
Authorization Mediator will validates the shared_secret hashes, call Resource Server validating access_token and return data.
Part four: refreshing access token;
After access token expires, Client will send a call to /refresh-token containing the Authorization header and some extradata with { payload: { grant_type, refresh_token, client_id, scope }, timestamp, hash ( some_user_data + timestamp + shared_secret ) };
Authorization Mediator will validates the shared_secret hashes, call Authorization Server and return a new fresh token access.
A visual image for this flow:
I don't think it is a perfect strategy, but it replaces Resource Owner Password Credentials to Authentication Code with PKCE and gives some extra security techniques. It's way better then a single and simple authentication method, preserves the OAuth2 protocol and mantaein a lit bit more hard to compromise user data.
Some references and support:
How do popular apps authenticate user requests from their mobile app to their server?
Why does your mobile app need an API key?
Mobile API Security Techniques
Secure Yet Simple Authentication System for Mobile Applications: Shared Secret Based Hash Authentication
Auth Code flow with PKCE is recommended - along with logging on via the system browser. Also the AppAuth pattern is recommended.
https://curity.io/resources/develop/sso/sso-for-mobile-apps-with-openid-connect/
It is tricky and time consuming to implement though - so you need to think about it - sometimes using a cheaper option is good enough. Depends on the sensitivity of data being exposed.
If it helps here are some notes for an Android demo app of mine, which also focuses on usability - and links to a code sample you can run:
https://authguidance.com/2019/09/13/android-code-sample-overview/
First of all, do not invent a OAuth grant simply because you need to adopt it in your application. It will make tings complex to maintain.
In your scenario you need to provide social login (ex:- Login via Google, facebook). This of course a desired functionality one must support. But it doesn't limit you from obtaining end user credentials through a custom registration process. There are many reasons for this, for example not everyone use social media or a Google account. And sometims people prefer to register than sharing user identifier of some other service (yes, this is the opposite end of social login).
So go ahead, provide social login. Store user identifiers when first login through external identity server (ex:- Google). But also, have a good old registration step with password and an email.

Using access_tokens and id_tokens together Auth0

While starting to integrate auth0, I came across this article
So its clear that to secure apis, all we need is the access_token and that is sent with each http request in the request Authorization header(Bearer scheme).
But then auth0(and possibly other providers) also send an Id_token that contains information about the user. My confusion is that how do I use this id_token to pass user information to my api. ( I have a spa running front end that authenticates to auth0 and gets these 2 tokens).
I can ofc call the userInfo end point in my api to get user info. But then wouldn't this defeat the purpose of the Id tokens?
The ID Token is consumed by the application and the claims included,
are typically used for UI display. It was added to the OIDC
specification as an optimization so the application can know the
identity of the user, without having to make an additional network
requests.
So my question is how do I access user profile in my api using id tokens?
"My confusion is that how do I use this id_token to pass user information to my api"
for that confusion, you just pass your JWT token. while generating JWT token, you need to add user information in payload part in JWT token. When your api get the JWT token, just check your JWT token is correct or not by the use of secret key and if correct, you can get data. How to get is just go from that JWT Authentication for Asp.Net Web Api
ID token is sent from the authorization server as a part of OIDC protocol. The purpose of this is to authenticate the user to your client application (SPA in this case). i.e. to let your API or the application know which particular user authorized the client to access a certain resource on its behalf.
Best way to use the ID token is by decoding and verifying it using a library. This will allow you to verify the signature of the token and any other claim that is included in the token (you can add custom claims to the tokens). Validation of those claims can be used to determine identity of the user and match with the user profile in your API. You will have to check the documentation related to your IdP(auth0) to figure out how to add new claims that are used by the user profile in your API.

Apigility and oAuth for users

I'm about to start working on application with rest API and I want to use apigility. There is one problem unfortunately with this idea. I cannot find reliable source of information how to allow for authentication by oAuth for regular users.
I need to provide access for angular app and native mobile one (possibly in future for third-party web apps). All resources that I have found are about granting access to api for specific client application, not for specific users that use this applications. I don't want to implement two different authentication methods, so if there is a way to resolve this issue with apigility it would be great.
Do you have any suggestions how to approach this? I know that I can generate client id and secret for all registered users but this seams a little crappy solution and I have database schema already in place for storing user info.
What you're likely looking for is the "password" grant type. In this scenario, you will have a way of registering users and their passwords, and then a "login" screen of sorts. This login screen will send the following information:
username
password
client_id -- this will be the OAuth2 client ID (not the user ID!) for the application
"grant_type": "password"
Note that you are NOT providing the client_secret in this scenario! In the case of a user credential scenario, the user's credentials are validated, and then the server verifies that the client_id supports this grant type.
If the user provides successful credentials, then the OAuth2 endpoint will return a token, a TTL, and a refresh_token (which, if you send it before the TTL expires, will give you a new set of tokens).
From here, you will then send the token in the Authorization header: "Authorization: Bearer ". Apigility will then pick this up on each request and validate the token.
The validation returns also the username as part of the identity. This means that you can query the ZF\Mvc\Identity to retrieve the user in order to perform user-specific ACL assertions later!
Poke me on the mailing list (http://bit.ly/apigility-users) if you need some more direction.

Login to mobile app and web app using oAuth

We have a SSO system which is used by our web applications and we are planning to also write some new mobile/desktop applications. I have been reading about using oAuth 2.0 so a user can natively login using the app (using the password grant type), retrieve an access token and access functionality using the REST web services. The problem is all functionality will not be available within the app, in some cases we have to redirect the user to the web application via a browser. I have read we shouldn't pass the access token in a URL so is there anyway to use oAuth to login to the web application automatically without the user having to submit their username and password again?
Any advice would be much appreciated.
In the mobile app, you could create a nonce (a token that should be used no more than once). Then, add this to the URL when opening a link to the Web page. This token should have some sort of identifier in it. The Web app that serves that page should track these IDs to ensure that it's not sent multiple times (thus, making it a nonce). This would be independent of the OAuth-based authentication. So, a request might look like this:
GET /anything?nonce=eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI5N1Y2ZU9WWlo1VGpPR3dWIiwiY2xpZW50X2lkIjoibXktZ29vZC1tb2JpbGUtYXBwLTIyIiwiYXVkIjoiaHR0cHM6Ly9leGFtcGxlLm9yZy9wYWdlLXRoYXQtaXMtbm90LWluLW15LW1vYmlsZS1hcHAiLCJleHAiOjE1OTg3NTI0NDB9.JoDstXRnC23PE8ZCqk-U-IzSNp_cUYa12HbajI1KGlF-OwRR46QRC_V7brcGOVdo5_Aw1RdpssNWCVFiGDeTBc8wi1lIJW-rgEGH5J1qUi8rL1T-yfy3vdLGPYzJMtHvCeyoEjgmoYOtZcpPSQScBJSRvId3Hdu3QgwcelSwljkeNJbZRCnG25HIqJfC1Cjm9vqHhvUGqtzbgVBUPnICiI8EZyGe3SpH2P4SxctLcgzWad8zJeyPFki3yfBHpqQ3mBWy0BbVdjzgD0mj323q1LWHR4kNkrH7cUJgAg4PlWahOW7Q4qcT3CBJYNtlh008ARqK7XagEQKX45vv5TfSlk2q7Zy06RnV2XwZXfLpyh-ZfURpcsxEJ3O-4NY71XxEqUtEyuisjQdZx5m95uzSrzk75F-ruQ3KYIouiAOAUDuMtFwhwjF68VdDeC4Zwt2q3BHzMBBp-8k1bAXq8e4dmHz0Jbuo9R8MJ2zSrVK6is5nNtNoJvYoXgc0WTA8MFqBj316cT_ouu-U1nTL3GR5sJ_lxorhP6xz0CqNxNY_90-JwOUB0UibUryRiXt-SUPJga36pBQ8eO8--Xupx_WU7CDIFdFvnLgJahD-4KmZcga6wCoqd-KKw3H5-jtbit06XMrKkDiWjz2g4eYhPR6xipbnqyZaaCwtYN4mAMz86ug HTTP/1.1
Host: example.org
Accept: */*
When the JWT-encoded nonce is decoded, you can see this header:
{
"alg": RS256
}
and this body:
{
"jti": "97V6eOVZZ5TjOGwV",
"client_id": "my-good-mobile-app-22",
"aud": "https://example.org/page-that-is-not-in-my-mobile-app",
"exp": 1598752440
}
Now, the API could decide if the nonce is acceptable by:
Check that it's URL is the same as the aud (audience) claim
Check that the nonce has never been seen before (using the jti, JWT ID, claim)
Check that this resource should be possible for this client to request (using the client_id claim)
Check that the nonce wasn't created too long ago and is still valid (using the exp or expires claim)
The signature of the JWT is valid. This can be done using the public key of the client.
Doing like this could lead to a spaghetti of trust, however. To avoid this, your OAuth server could instead embed a nonce into the app's ID token, or allow the client to request new ones as needed (by performing token exchange e.g.). Then, the API only has to trust the OAuth server, and doesn't need to keep track of the client's public key. If you only have a handful of clients, this won't be hard to mange though.

Resources