I am using Open ID Connect and requesting tokens from Azure Active Directory. I am using the authorization code flow, so I am receiving both the id_token and the access_token. I am using .NET Core.
My configuration of Open Id Connect is as follows:
options.Authority = options.Authority + "/v2.0/";
options.TokenValidationParameters.ValidateIssuer = false;
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
Notice the Save Tokens set to true
When the user is logged in, I am able to retrieve both the tokens as follows:
string accessToken = await HttpContext.GetTokenAsync("access_token");
string idToken = await HttpContext.GetTokenAsync("id_token");
My question is, where these tokens are actually being saved, and how can I configure how these tokens are being saved?
I also heard that in the authorization code flow, the identity provider will return the authorization code, and the server would then use that code to request the tokens. However, I am not doing any of that programmatically and I am still able to retrieve the tokens. Is this something handled automatically with Open Id Connect?
Where these tokens are actually being saved?
As the OpenID Connect protocol diagram architecture describe, When a new session is started, a new cookie is returned to control this session. This "sesion cookie" is created based on "ID Token" and as long as this cookie is valid, user will be considered as authenticated. As you are using, OpenID Connect (OIDC), it create the cookie and save token there. you could refer this docs
How can I configure how these tokens?
If you want to configure your token mechanism Microsoft provides library fro that. You can use ADAL or MSAL for your own configuration.
Is this something handled automatically with Open Id Connect?
Thought its has some background mechanism but you have to use authentication library to handle on your application code. You could refer official docs
For more details you could refer flowing docs
Authentication implementation
Authentication Libraries
Code sample
response_type is set to code indicating that you are using the Authorization Code Flow.
When you use OIDC auth code flow along with clientid and clientsecret to get token, the work process is as below:
1.The user clicks Login within the regular web application.
2.Auth0's SDK redirects the user to the Auth0 Authorization Server (/authorize endpoint).
3.Your Auth0 Authorization Server redirects the user to the login and authorization prompt.
4.The user authenticates using one of the configured login options and may see a consent page listing the permissions Auth0 will give to the regular web application.
5.Your Auth0 Authorization Server redirects the user back to the application with an authorization code.
6.Auth0's SDK sends this code to the Auth0 Authorization Server (/oauth/token endpoint) along with the application's Client ID and Client Secret.
7.Your Auth0 Authorization Server verifies the code, Client ID, and Client Secret.
8.Your Auth0 Authorization Server responds with an ID Token and Access Token (and optionally, a Refresh Token).
Related
I have a web app MyWebApp.
And two APIs: MyAuthAPI and MyServiceAPI, both RESTful NodeJS. MyAuthAPI uses HashiCorp Vault as a token store with OAuth2.
MyServiceAPI has CRUD operations available to authenticated clients.
There is no human login required (or desired) on MyWebApp. Any human can access MyWebApp through a browser and run the service.
At present, this is the (very insecure) flow:
MyWebApp sends clientid and clientsecret to MyAuthAPI to retrieve token. This token is then used for communicating with MyServiceAPI.
The obvious downside is that anyone can capture the clientid and clientsecret by simply looking in developer tools in a web browser. They could then use those to authenticate with MyAuthAPI, generate their own token, and make calls to MyServiceAPI without MyWebApp being involved.
So how do I best secure the entire application so that MyWebApp is safely and robustly authenticated without revealing the credentials?
Thanks.
ETA:
I want to be able to authenticate MyWebApp with MyAuthAPI and then use the generated token to connect to MyServiceAPI. But I don't want it to be possible that anyone can intercept those credentials - currently they can be see in the request header as "Authorization: Basic "
The MyServiceAPI endpoints must be secured so that only authenticated clients are able to access them. But when that client (MyWebApp) is a public website, how do I authenticate without making the credentials visible?
ETA2:
https://mywebapp.com is MyWebApp which is a React application.
https://myauthapi.com hosts MyAuthAPI
https://myserviceapi.com hosts MyServiceAPI
When I load mywebapp.com in a web browser, it authenticates with myauthapi.com/oauth/token to get a token. At present it does this by sending the creds in the header Authorization: Basic
The token that is returned is then saved.
The web application then tries to get the data from an endpoint on MyServiceApi using this token:
Authorization: Bearer
GET https://myserviceapi.com/objects
or POST myserviceapi.com/objects
or GET myserviceapi.com/objects/objectid
or DELETE myserviceapi.com/objects/objectid
MyServiceAPI verifies the token with MyAuthAPI, but that isn't public-facing, so there's no issue there.
The issue is that, as you can see from the attached screenshot of the Developer Tools console in Chrome, anyone using the web application can see the Authorization header containing the credentials, and could then use these credentials to programatically gain access to the auth API to generate a token which can then be used on the service API endpoints.
I want to restrict all access to the API servers to only come from specific applications, such as MyWebApp, on mywebapp.com.
First, I think this question could better be asked in https://softwareengineering.stackexchange.com/.
Second, where MyWebApp is deployed? How it is being used? If it works with https, then the body is encrypted, and when you send the clientId and clientSecret, you should send it in the body, so users will not be able to see them.
Client Credentials Grant should only be used by confidential Clients. Thats because you can't hide the client_secret on non confidential Clients. Your frontend seems to be a non confidential Client.
Normally you should use the Authorization Code Grant with PKCE. But you would need users to authenticate themselves for that.
Feels like you need an architecture design based on standard flows, since OAuth should work like this:
Web app signs user in via an Authorization Server, using Authorization Code Flow (PKCE)
Web app gets tokens from the Authorization Server
Web app calls API with an access token
API validates token using data from the Authorization Server
API then trusts claims in the access token and uses them for authorization
See my Initial HTTP Messages blog post for an example of how this looks.
Since local storage and session storage are both accessible via JavaScript it is best not to store the authentication JWT in either of them to avoid XSS attacks.
Since OpenID connect 2.0 is performed on a separate domain how do we set a server-side HTTP only cookie that contains the authenticated JWT?
My guess is this:
The user goes to your website then clicks sign-in.
The user gets redirected to the 3rd party OpenID connect 2.0 provider.
The user signs in and is now redirected to the route of your choice www.example.com/myredirectlogin.
The user's browser then makes a get request when the redirect lands on my route and it passes in the JWT token in the URI.
The server then validates the JWT via Asymmetric algorithm with the public key given by the provider.
The server then returns a server-side HTTP only cookie with the JWT as the value and the client-side doesn't have any recollection of the JWT since it was only in the URI and isn't stored anywhere else.
My question is: Is the above the correct process to securely handle OpenIDConnect 2.0 flow?
I'm assuming you mean the "Id Token" when you say "authentication JWT", since that's the only JWT required by OpenID connect.
All the flows that OpenID connect supports are listed in the spec. If you want to log in to the authorization server and authenticate to a separate site, then you will often use the "authorization code" flow which doesn't send the ID token to the browser at all. There are other flows defined by OpenID connect, but none of them mention storing the ID token in a cookie - how the session is maintained between the client (the site you're authenticating to) and the browser is a separate issue from authenticating the user.
I found the answer within authorization code flow: https://connect2id.com/learn/openid-connect
List of steps
OAuth 2.0 and OIDC Authorization code flow
The user hits your website's login route
The user is redirected to an identity provider with a proper tenant id
The user is authenticated and is redirected to your callback route with an access token in a query parameter i.e. &access_code=234234sdfkljsak.
a get request is executed on your web server at the callback route with the access token in the query parameters.
this callback get route should then make a post-call to retrieve an actual JWTidentity token from the provider i.e. azure b2c and it will add the access token as part of the request either as a query parameter or post of body.
the provider (Azure B2C) then will respond with an identity JWT token that we will send back to the user's browser as an HTTP-only session cookie that way the user is now SSOed among all browser tabs and the cookie will be sent with every request automatically and is protected from xss.
Let's say you are developing a client side JavaScript SPA app (Angular), a backend API for this app (ASP.NET Core in my case) and you use an identity provider that implements Open ID Connect protocol (I'm using IdentityServer4).
Apparently the recommended way for securing the app is to use the OIDC implicit flow between the JavaScript app and the identity provider and if successful the JavaScript app gets an id token and an access token.
Now according to this documentation the JavaScript app is supposed to pass the access token in the headers whenever it calls the API. And I'm not sure what purpose does the id token serve in this case (besides customizing the UI in your JavaScript app)?
But this is the confusing part: The documentation also says you should never use the access token for authentication. But that is the token that my API receives in the request headers, how can it authenticate the user then? If my API receives Post(newRecord), and the API needs to internally fix some audit information on newRecord (i.e newRecord.CreatedBy = CurrentUsername), how can it do that without authenticating the caller??
I think I'm missing a piece of the puzzle. Please any help is deeply appreciated.
Short answer/suggestion
Use Access Token to access API endpoints. From API endpoints, you must use token introspection endpoint to validate token validity (active state) as well as obtain subject who authenticated at authorization server. IdentityServer provide support for this. Documentation is available from here.
Explanation
ID token is intended to be used by receiving client. It will allow your client to authenticate the end user and provide user specific customizations. This is the whole purpose of OpenID Connect (OIDC). On the other hand OAuth 2.0 provide an authorization framework. It replaces user credentials with access tokens, thus improving API access security (compared to basic authentication and storing user credentials everywhere). Hence OIDC is built on top of OAuth 2.0, you get both ID Token and Access token with OIDC flow.
But as you have figured out (and mentioned before), ID token is intended for client. There are could be exceptional cases where ID token get passed between client and a server. This is mainly when both are controlled by same party. But the access token is the key to access API endpoints, correctly.
Access tokens can be an opaque string or JWT. When it's a JWT, API can read and understand the token (self-contained). When it's opaque, only way to validate token at API endpoint is to use token introspection endpoint. If API can validate token validity, then it could grant access (authorize) request. Furthermore, if user details (subject) are available (through JWT or as introspection response), then user specific checks can be executed. This further extends to token scope values. But at the end of the day, you are authorizing the API request and not authenticating the user at API endpoint. That's the highlight. Hope things are clear now.!
I am using this library: https://github.com/manjeshpv/node-oauth2-server-implementation
From my understanding of Oauth2:
1)Generate a clientid and clientSecret
2)User use clientId and clientSecret to get a bearerToken
3)Authorisation server returns accessToken to users if valid clientId and clientSecret combination
4)User then use the accessToken to run http post/get api calls (within their scope)
In the POSTMAN examples given in the GITHUB, we have
I noticed Password Grant, Refresh Token ,Client Credential Grant and Authorisation Grant points to the same POST request with the difference in the body.
and the Authorise sample web service, which I assume is that user would have to click in order for the authorisation server to return an access code for user to call scope specific API urls, but somehow access code is needed too, which I'm confused.
and If I use Client Credential Grant (which I assume is to return an AccessToken using my clientId and clientSecret), then what's the point of the authorise webservice?
What would be the right flow for this library and webservices example?
Would really appreciate help in this, thanks!
and the Authorise sample web service, which I assume is that user
would have to click in order for the authorisation server to return an
access code for user to call scope specific API urls, but somehow
access code is needed too, which I'm confused.
Your terminology is a bit confused. Here is a probably most popular OAuth flow:
Developer (you) registers OAuth client, receives clientid and clientSecret
User opens some url like oauth.com/authorize, is shown a dialog asking to give some rights to developer's application. (Here clientId is used, but clientSecret is not required)
If user agrees, authorization code is sent to developer's application (to redirect_uri defined at step 1). This code is short-term and cannot be used to access user's data.
Developer's application makes POST request to OAuth server with authorization code, clientId and clientSecret and gets authorization token in exchange. This token can be used to access user's data.
and If I use Client Credential Grant (which I assume is to return an
AccessToken using my clientId and clientSecret), then what's the point of the authorise webservice?
Token got by ClientCredentials grant identifies client, but not user. So I guess it is useless in your case.
I started working with instagram APIs using node.js and walked through the official instagram API docs here but it does not explain clearly.
Here I have 2 questions:
what is the difference between Client ID and Client Secret?
what is access_token ? and what is it used for ? and
when we should request for it ?
The client ID is is basically a unique id assigned to your application by an Oauth provider. It considered public information, and is used to build login URLs, or included in Javascript source code on a page.
An app requesting an access token has to know the client secret in order to gain the token. This prevents malicious apps from ever obtaining a valid access token. The client secret id doesn't state anything about authenticating a user, but it's instead for authorising an app to request access tokens.
The client secret must be kept confidential. If a deployed app cannot keep the secret confidential, such as single-page Javascript apps or native apps, then the secret is not used.
When you login with an Oauth provider, the server responds with an access token and expiration time in ms if the login is successful.
{
"access_token":"RsT5OjbzRn430zqMLgV3Ia",
"expires_in":3600
}
Every time client requests a resource from the server, the server validates the access code. The access-token is used to verify every request from the client. You will request for an access_token whenever you login through an Oauth provider.
You can refer this and this for more information.