Does OAuth uses ID Tokens for profile Information? - oauth-2.0

When we register to Spotify using Google or Facebook we'd using OAuth . But OAuth is used for authorization . When used generates access tokens for specified API or resource . But when we use OAuth , it sends our profile pic and username too . Does it means it's using ID tokens (Open IDConnect ) as well for generating profile information .
And when logging in via Facebook , why do we require access tokens when we using them for authentication , instead we require ID tokens . Am I correct ??

OpenId Connect is authentication and uses id token, and Id token basically says yes there is a user behind this machine who has logged in and granted access.
Oauth2 is just for authorization to authorize an application to access data on behalf of a user. an access token is granted to the application authorizing it to access the data on behalf of the user for a certain amount of time there is no grantee when using an access token that the user themselves is actually their accessing the data.

Related

Where to get Gitlab's OpenID ID Token?

Using Gitlab provided access tokens for the OpenID scope, i.e.
https://gitlab.com/oauth/userinfo?access_token=<bearer token>
returns a limited amount of information e.g. username, groups, etc. However, it does not return the user's email address.
The Gitlab documentation indicates that:
The claims sub, sub_legacy, email and email_verified are included in
the ID token, all other claims are available from the /oauth/userinfo
endpoint used by OIDC clients.
Given the AccessToken - how do I retrieve the ID token?
*This is a known / discussed issue cf. here
It all depends on what scopes you ask for when you first send the initial authentication request to GitLab.
You need to ask for the email scope to get that information back and you should get the ID-token back at the same time as you get your first access-token.
When you obtain code through authorization request, you need to specify the scope, and the scope needs to include openid,read_user,profile,email.
When exchanging the token with the code obtained in the first step, you can return to access_token and id_token.
When the access_token obtained in the second step is used to obtain the user information, it can return the user's e-mail.
Refer to the explanation of the scope used above:
openid: Grants permission to authenticate with GitLab using OpenID Connect. Also gives read-only access to the user's profile and group memberships.
read_user: Grants read-only access to the authenticated user's profile through the /user API endpoint, which includes username, public email, and full name. Also grants access to read-only API endpoints under /users.
profile: Grants read-only access to the user's profile data using OpenID Connect.
email: Grants read-only access to the user's primary email address using OpenID Connect.

Open ID Token vs Oauth Token

I am new to OAuth and OpenId, and after reading multiple pages and information I still do not feel confident at all.
My goal would be to create an iOS Application that communicates with my BE. I need the iOS app to authenticate the user to access their resources.
Reading about OAuth, the solution seems to be straight forward. Just use the Authorization Code Flow with PKCE to make the App have an Access Token. This way I am authorizing my iOS app to access user's data. When the iOS app calls https://example.org/user with the access token, the resource service (my BE server) can get the access token and call the introspection API to know to which user the access token is bound to, and return the correct user data. Since authorization needs authentication to be made in the first place, having the access token would mean that the user is (or at least was) authenticated.
First thing that confuses me: According to the OAuth specs, OAuth is not an authentication protocol, but still the protocol authenticates the user using the user's credentials. Why is OAuth asking the user for credentials, instead of relying on another protocol/flow for user authentication? Such protocol would just acknowledge to OAuth that the authentication was successful.
This first issue made me start reading about Open ID Connect specification and the ID Token. This token would be received by the iOS app. What is the iOS App supposed to do with it? I can already get the user information calling the /user endpoint. How would this ID Token be an advantage?
tldr
Access token (OAuth 2.0) - authorize against OAuth protected
endpoints.
ID Token (OIDC) - authentiation by client application.
Authorization server authentication - It's there to detect
authenticity of end user involved in both protocols (pseudo
authentication from client application perspective)
OAuth is not an authentication protocol, but still the protocol contain a step to authenticate the user using the user's credentials
Correct, OAuth is not an authentication protocol. It is for authorization, which means identifying there are correct access grants to access a protected resource (protected resource ? ex:- An API, A photo stored in a backend).
So why you see end user login dialog ? Well that is the job of authorization server. It authenticate end user to be known by it and then issue the access token to client (client == in simple terms the application which end user uses). So yes there is an authenitcation happening, but this is not applicable to your client application or protected endpoint. One can define this as an pseudo authentication.
OpenID Connect - For authentication of client application
In the original RFC (RFC-6749), OAuth 2.0 was defined as a framework. OpenID Connect was an extension that built on this framework. What it provide ? Well as you found out, it introduce the ID Token. And ID token is issued by authorization server to be consumed by your client application. It contains end user identity information in JWT format. By validating integrity of this token, your client application can authenticate the end user. And access token ? That's there to used against protected endpoint. It doesn't say anything about end user to client.

OAuth2 Login (Not Authorization)

I have implemented an OAuth2 register workflow (in Java) according to rfc6749
I'm using GitLab as OAuth2 Provider.
After the user granted access to my application for his account, I get an OAuth Token (along with refresh token and other stuff), I am able to make API requests on behalf of the user, so this is working fine.
This way I can get the users e-mail adress which I use to create an internal user.
My questions are:
Is it practice to issue a token that is generated by my application for the user (along with the OAuthToken) or should I just use the token that has been issued by the OAauth Provider? (My App also has local auth with bearer tokens). This token will be used for further API - CLIENT communication (stored in Angular2 local storage as bearer)
How to do login only? When a OAuth User accesses my web service, how do I know that this user is a OAuth User and which OAuth Token belongs to him? How can the user login without providing e-mail or password? (The user has no password) I guess I have to redirect him to the OAuth Provider again, but I don't want my user to grant access everytime he logs in.
Answer 1:
Though you can use the token provided by OAuth provider, you SHOULD NOT use it considering the risk that may arise exposing it to the public.
Instead you should securely save the token provided by OAuth provider into the database and use another token for authentication of further api calls. (you could use JWT)
Answer 2:
There are two types of systems
Which always uses OAuth provider for identifying user. (Ex. Tinder)
Which provides both OAuth Login and Traditional login/signup. (Ex. Quora, Instagram)
If you want your application to follow 2nd approach, you should ask the user to create password for the first time when the user logs in using OAuth provider.
This will allow the user to log into your application by both methods, traditional as well as OAuth
To identify users of your application, you should either use HTTP session or issue your own tokens. Do not use tokens generated by the OAuth2 provider - they are meant to be used just by your backend (in role of an OAuth2 client).
To use an external authentication in your application, you probably want to use OpenID Connect, not a bare OAuth2. OpenID Connect extends OAuth2 and it's meant for authentication instead of the rights delegation. Then you use an implicit flow (instead of authentication code grant) with scope=openid, your frontend app (HTML+JavaScript) gets an ID token signed by the OAuth2 provider. After successful signature verification, your backend can trust that the client is the one described in the ID token (in its "sub" field). Then you can either keep using the ID token or generate your own token.

how do azure ad provider validate token and user access permission to the applications?

when using AZURE AD for authentication we get a token for a successful login which we pass to the resource server or api controller.
In my case I have 4 applications in my directory WebApp1, WebApp2 ,ApiApp1, ApiApp2 & 2 users - user1 & user2
All the users are assigned to all applications.
But only WebApp1 has permission to ApiApp1 & ApiApp2 , WebApp2 has permission to ApiApp2 only.
My question here is how do the AAD provider at applcation end validate the user token and permissions?
When I observe using fiddler I dont see any calls being made to the authority (AAD) for validating the token and app permissions?
How does the AAD provider at application end make sure it is issued by a valid AAD and the user has permission to the application ?
In case it is a API app how does the AAD provider make sure that the app to which the token is issued has permission to the web app?
So there are multiple questions here so I'll try to answer all of them as best I can.
The applications only check the tokens are signed with the correct keys by verifying their digital signature. Typically there would be one call to the authority to get the signing public keys when the app starts. If you can't see one, it's either because Fiddler can't see it or because the library in question is not validating the token(!). In case of an app I have that uses the OWIN OpenId Connect middleware, I can see a call to https://login.microsoftonline.com/tenant-id/.well-known/openid-configuration, and then https://login.microsoftonline.com/common/discovery/keys, which is where the signing public keys are.
The user's permission to the app are in their claims. When you add a delegated/app permission to an app, you always define a value. These values are sent in the token. App permissions are in a claim called roles (IIRC), and delegated are in scp. Azure AD will only put the claims there for the permissions given to each app/user. Your app trusts AAD to do the correct thing (and verifies with the signature it was indeed AAD).
That goes for both Web and API apps actually. If you try to sign in to the front-end app through Authorization Code Grant Flow for example, the user will get an error message that they are not allowed to access the app. AAD will not send an authorization code/id token back for this user. If you got one, they are fine.
Your WebApp1 cannot call ApiApp2 because AAD will not give it an access token to it.
In my case I have 4 applications in my directory WebApp1, WebApp2 ,ApiApp1, ApiApp2 & 2 users - user1 & user2
All the users are assigned to all applications.
But only WebApp1 has permission to ApiApp1 & ApiApp2 , WebApp2 has permission to ApiApp2 only.
If that is your scenario , you could follow below steps :
In Azure AD portal , create WebApp1, WebApp2 ,ApiApp1, ApiApp2 .
In configure page in WebApp1 , in section “permissions to other applications” , click add application :
select “All Apps” ,find the ApiApp1, ApiApp2 (here I only select one app for example):
add access permission to the selected api app:
You need to add access permission to ApiApp1 & ApiApp2 in WebApp1 and add access permission to ApiApp2 in WebApp2 . To assign user , you could click User and groups tab in WebApp1 and WebApp2, assign the users(user1&&user2) or group you want:
some additional notes for great answer from #juunas :
My question here is how do the AAD provider at applcation end validate the user token and permissions?
Usually a client app would validate a token for its crypto algorithm ,token signature and token claims, for example : issuer — does the token originate from the expected IdP. audience — is the token intended for me? timestamps — is the token within its validity window . You could use JwtSecurityTokenHandler to validate the token .In Azure AD V1.0 endpoint , the issuer will be "https://sts.windows.net/Yourtenant/" and as #juunas said , it will query Azure Ad public keys during validating token signature .You could refer to code sample here for how to validate JWT token in c# .
Using OWIN middleware will help you perform such validation easier , you could refer to this code sample for mvc app sign Azure AD users in with OpenID Connect and calls a web api using OAuth 2.0 access tokens. In your scenario , you want an app to call another API APP , you could add below code to get access token for API:
string resource = "http://testbasic1.onmicrosoft.com/testrole"; //Your API APP
string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID));
ClientCredential credential = new ClientCredential(clientId, appKey);
var result = await authContext.AcquireTokenSilentAsync(resource, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));

how to identity a person when login with oauth2

In OAuth1.0,the access_token and the access_secret is unique for every user in the third party system(like facebook).so when i login by Facebook,it returns me the access_token and access_secret,i can register a user in my site and login.
In OAuth 2.0,it only returns access_token,and expires time.and the access_token may expire after several days. how to identify a person?(or must i request it's api to save the uid of facebook to reach this goal)?
Keeping track of users is completely in your responsibility and not part of OAuth. OAuth just specifies how you can get access using an Access Token to a provider API.
So yes, you have to fetch the user info from Facebook to get the unique ID. ;)

Resources