What is the main reason OAuth2 is not enough for authentication?
I can see that if userA logs into evil.com, then owner of evil.com can submit userA's access_token to good.com (or any other login with fb website) and pretend to be userA.
But if good.com checks if access token was intended for it, then I don't see any possibility of attacks..
I can't see the fuss about this. For example facebook gives me the App id when I get the access_token details. How is an attack possible if I am checking this?
Is it not a security vulnerability but lack of standards? like which scope or which field email is in etc.?
The access token you receive just represents an authorization issued to the client. It just allows the client to access on protected resources, but it does not give you any information about the resource owner.
In your example, evil.com can get those resources that own the userA, but cannot know who userA is.
Please loook at this excellent video about OAuth2 and the Authorization/Authentication terms. It helped me a lot.
The access token does give you information (possibly) information about the Resource Owner but it does not give you information about whether the Resource Owner is present and/or how he/she authenticated even if you'd be able to identify whether the token was meant for you in some undefined non-standard way (the latter being another advantage of OpenID Connect over OAuth 2.0 as the OP already mentions).
Related
We have OAuth2 on our website, and according to our logs, we redirect users to URL like this:
https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=xxxx&prompt=consent&redirect_uri=xxxx/callback&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&state=Y38pUwFTAqbaHsU6oa4q
The next log entry is redirect callback from Google, which is missing www.googleapis.com/auth/youtube.readonly scope:
https://ourapp.com/oauth2/callback?state=xxxx&code=xxx&scope=email%20profile%20openid%20https://www.googleapis.com/auth/userinfo.profile%20https://www.googleapis.com/auth/userinfo.email&authuser=0&prompt=consent
What may be a reason for this behavior? It happens only to some users, and very inconsistent. I wasn't able to reproduce it by myself.
The application is approved by Google and the scope usage is verified.
For apps that request more than one scope (you are asking for identity scopes email, profile and YouTube), you must be able to handle partial consent where the user may choose on the consent page to not grant access to one or more non-identity scopes.
https://developers.google.com/identity/protocols/oauth2/policies#unbundled-consent
You can encourage your users to grant access to the scope needed by separating the sign-in moment (asking for email, profile) information from the moment of asking for YouTube access. This is called incremental authorization.
You can also tell your users before you redirect to the OAuth flow why you are asking for the data you need to let them make a more informed choice.
I'm in the process of converting an internal C# API that uses a legacy SOBO integration to one that uses OAuth 2.0 as required by DocuSign. The legacy application makes all requests to DocuSign using DocuSign credentials of an application user (a non-person) and injects SOBO data (email address) in the appropriate header when we need to generate an embedded sending URI and have it appear that the envelope was sent by a real person without using their credentials.
I have successfully converted another (non-SOBO) internal API using JWT grant, but I do not know how replicate the SOBO dependent workflow. Have read Matt King's article "From the Trenches: OAuth 2.0 and the new SOBO", but still a bit confused. I know how to extract userId from email address as mentioned in the article, but not sure what do with it. Similar to my legacy application, I am using a application user to get consent and ask for JWT token without prompting internal users for their consent. Is this still possible using OAuth 2.0?
Happy to help here. Once you've retrieved the user's apiUserName / userId you'll want to add it into the JWT assertion's sub line.
When you go to generate the token, if consent has not been provided by or for the user, our system will send back an error of "Consent_Required." See https://www.docusign.com/blog/developers/oauth-jwt-granting-consent for different methods of granting consent.
For individual consent, the user needs to go to a specific URL containing your clientId, redirectUri, and some additional scopes. If they hadn't previously consented to the scopes in your OAuth request they will be prompted to do this once. You can confirm consent has been applied by having them visit the same link afterwards, which will send them directly to your redirectUri.
Domain consent works a little differently -- you need to have an organization, a claimed domain, and the users you're providing consent on behalf of need to have an email address that is part of that claimed domain.
Happy to connect and walk you through it -- if you can open a ticket at support.docusign.com and in the details request they reach out to me I should be able to have the case transferred and work with you from there.
Regards,
Matt King
I currently have a backend running on AWS Lambda and I'm using DynamoDB as a database. In Dynamo, there is a list of users and each user has specific permissions as to what routes they have access to through the API. There is no issue here.
I have not built the front end yet, but I will be logging in users using Google Auth, more specifically with the react-google-login component.
My question is: Once a user is logged in to the site, should I trust the JWT from Google (after verifying its legitimacy
here with the Google API) which returns the user information (Name, Email), lookup the user item inside of Dynamo to retrieve their permissions, and then serve their request?
This seems like the logical thing to do but I was looking for some confirmation. My one worry is that someone could use a supervisors name & email to authorize a request but if the lambda must accept a JWT created by Google as entry, I believe this problem is solved correct?
I have API Keys as well for every user for some external functionality, but I have that covered since it's just a Dynamo call away. My only concern is with the front end requests to Lambda since I do not want to roll my own auth/jwt.
Here is what I was envisioning.
Thank you!
Normally you should use access tokens for that purpose. The ID token should be meant only to authenticate the user, and the access token should be used to authorize access.
The best scenario would be to have a separate Authorization Server which could issue access tokens, and there are some open source solutions out there which you can use.
If you really don't want to setup your own AS then you could follow the scenario you outlined - the part with verifying JWT from Google and checking permissions in the DynamoDB is what the Authorization Server would normally do to issue an access token.
Just remember to thoroughly validate the incoming JWT - not only the signature with Google, but also check if that is a token created for your client / audience, etc. Otherwise someone could take a Google ID token JWT from their client and gain access to your API. This article lists best security practices when working with JWTs.
Also remember that ID tokens might have short expiration times and there are no means of automatically refreshing them (like you can do it with a refresh token in case of an access token), so you might end up having to reauthenticate quite often.
I am using Identity Server 4 for authenticate user from a single application page. For the need of the project, I have to use the resource owner password flow.
Identity Server and my application work fine together. Identity Server give an Access Token and I can use this token to access some API that we own.
However, I was asking myself about the Access Token, users and socpes. For now my setup is this one.
I have an API that require the scope API-1.
I have a client (my SPA) where I defined the scope API-1
And I have a user.
In this configuration, it is the client who own the right to access the API, not the user. And I'm wondering how to give this scope to the user and not anymore to the client.
Stupidly, I'm wondering if user can own the scope and not the client. Maybe I've miss or misunderstood something, so please teach me.
In the Resource Owner Password Flow your client will always need to have permission to the scope that your resource is protected by. This does not mean that you cannot protect your API based on claims related to the user however.
If in your API for example you need different permissions based on the user accessing the API look to use the claims information as part of your authorization. In the Resource Owner Password Flow example at http://docs.identityserver.io/en/release/quickstarts/2_resource_owner_passwords.html you will see that it mentions this at the foot of the page, see the two paragraphs as follows:
When you send the token to the identity API endpoint, you will notice one small but important difference compared to the client credentials grant. The access token will now contain a sub claim which uniquely identifies the user. This “sub” claim can be seen by examining the content variable after the call to the API and also will be displayed on the screen by the console application.
The presence (or absence) of the sub claim let’s the API distinguish between calls on behalf of clients and calls on behalf of users.
I am writing an application which will connect to multiple email servers using OAuth. As part of initial connection establishment, user will be prompted to give access to application. After granting access, it will redirect to the url provided while registering the application in OAuth API.
Now i want to identify for which user the access token and refresh token belongs after redirect url comes to my application. I want to treat all requests happening in one user session as unique. Can someone help me.
I'm not 100% sure I followed your question, but my understanding is that you want to determine some of the information about the user that's just logged into your API client. You can get email addresses by requesting the https://www.googleapis.com/auth/userinfo.email scope and running a oauth2/userinfo GET request:
gapi.client.oauth2.userinfo.get().execute(function(resp,raw)...
Depending on which scopes you have access too, you will also get a display name and some other info. Best bet is just to console.log(resp) and pick out what you want to use.