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.
Related
When I enter a some websites (YouTube, Spotify...) in the browser (not connecting as a registered user),
some http requests are performed in order to fetch the relevant data (for example a podcast episode on Spotify).
This http request are passed with access token.
How can I get a new access token by writing a code for it, without registering to a user account?
Where can I get more info about how those websites give access token to the browser without obligating the user to sign in first?
thanks!
I've tried to look into OAuth 2.0 but I'm not sure it's relevant.
For the past 10+ days I've read an watched ALL the content I could find on understanding OAuth2 and OpenID Connect, only to find that many people disagree on the implementation, which really confuses me.
To my understanding, all the articles and examples I found assume you want access to eg. google calendar, profile info or emails if you eg. login with google, but I do NOT need to access other than my own API's - I only want to use Google, Facebook etc for logging in, and getting an id which I can link to my user in my own database - nothing more than that.
I'll try illustrate my use case and use that as an example.
A note on the diagram: the Authentication service could probably be built into the API Gateway - not that i matters for this example, since this is not about "where to do it", but "how to do it the best way" possible, for an architecture such as mine, where it's used for my own API's / Microservices, and not accessing Google, Facebook etc. external API's
If you can understand what I'm trying to illustrate with this diagram above, please tell me if I've misunderstood this.
The most basic requirements for this architecture you see here are:
Users can login with Google, Facebook, etc.
The same login will be used for all micro-services
OpenId user will have a linked account in the database
User access is defined in my own db, based on groups, roles and permissions
I do not intend to use external API's after the user is authenticated and logged in. No need for ever accessing a users calendar, email etc. so I really just need the authentication part and nothing else (proof of successful login). All user access is defined in my own database.
So a few fundamental questions comes to mind.
First of all, is OpenID Connect even the right tool for the job for authentication only (I'll have no use for authorization, since I will not need read/write access to google / facebook API's other than getting the ID from authenticating)?
People generally do not agree on whether to use the ID or Access token for accessing your own API's. As far as I understand the ID token is for the client (user-agent) only, and the access token is for eg. accessing google calendar, emails etc.... External API's of the OpenID Provider... but since I'll only be accessing my own API's, do I event need the access token or the ID token - what is the correct way to protect your own API's?
If the ID token is really just for the client, so it can show eg. currently logged in user, without going to the DB, I have 0 use for it, since I'll probably query the user from from the db and store it in redux for my react frontend app.
Dilemma: To store user details, groups, roles and permission inside JWT or not for API authorization?
By only storing the user identifier in the token, it means that I always allow authenticated users that has a valid token, to call endpoints BEFORE authorization and first then determine access based on the db query result and the permissions in my own database.
By storing more data about the user inside the JWT, it means that in some cases, I'd be able to do the authorization / access (group, role, permission) check before hitting the API - only possible with user info, groups, roles and permission stored inside a JWT issued upon login. In some cases it would not be possible due to eg. the CMS content access permissions being on a per-node level. But still it would mean a little better performance.
As you can see on the diagram I'm sending all API requests through the gateway, which will (in itself or with an authentication service) translate the opaque access token into some JWT with an identifier, so I can identify the user in the graph database - and then verify if the user has the required groups, roles and permissions - not from an external API, but from my own database like you see on the diagram.
This seems like a lot of work on every request, even if the services can share the JWT in case multiple services should need to cross call each other.
The advantage of always looking up the user, and his permissions in the db, is naturally that the moment the user access levels change, he is denied/granted access immediately and it will always be in sync. If I store the user details, groups, roles and permission inside a JWT and persist that in the client localstorage, I guess it could pose a security issue right, and it would be pretty hard to update the user info, groups, roles and permissions inside that JWT?
One big advantage of storing user access levels and info inside the JWT is of course that in many cases I'd be able to block the user from calling certain API's, instead of having to determine access after a db lookup.
So the whole token translation thing means increased security at the cost of performance, but is is generally recommended and worth it? Or is it safe enough to store user info and groups, roles, permissions inside the JWT?
If yes, do I store all that information from my own DB in the ID Token, Access token or a 3rd token - what token is sent to the API and determines if the user should be granted access to a given resource based on his permissions in the db? Do I really need an access token if I don't need to interact with the ID providers API? Or do I store and append all my groups, roles, permissions inside the ID token (that doesn't seem clean to me) issued by OpenID connect, and call the API and authorize my own API endpoints using that, even if some say you should never use the ID token to access an API? Or do I create a new JWT to store all the info fetched from my database, which is to be used for deciding if the user can access a given resource / API endpoint?
Please do not just link to general specs or general info, since I've already read it all - I just failed to understand how to apply all that info to my actual use case (the diagram above). Try to please be as concrete as possible.
Made another attempt to try and simply the flow:
The following answer does only apply for a OpenID Connect authentication flow with a 3rd party IDP (like Google). It does not apply for an architecture where you host your own IDP.
(There are some API gateways (e.g Tyk or Kong) which support OpenID Connect out of the box.)
You can use JWTs (ID token) to secure your APIs. However, this has one disadvantage. JWTs cannot be revoked easily.
I would not recommend this. Instead you should implement an OAuth2 authorization server which issues access tokens for your API. (In this case, you have two OAuth2 flows. One for authentication and one for authorization. The ID and access token from the IDP are used only for authentication.)
The following picture shows a setup where the API gateway and authentication/authorization server are two separate services. (As mentioned above, the authentication/authorization can also be done by the API gateway.)
The authentication flow (Authorization Code Grant) calls are marked blue. The authorization flow (Implicit Grant) calls are marked green.
1: Your web app is loaded from the app server.
2a: The user clicks on your login button, your web app builds the authorization URL and opens it. (See: Authorization Request)
2b: Because the user hasn't authenticated and has no valid session with your authorization server, the URL he wanted to access is stored and your authorization server responds with a redirect to its login page.
3: The login page is loaded from your authorization server.
4a: The user clicks on "Login with ...".
4b: Your authorization server builds the IDP authorization URL and responds with a redirect to it. (See: Authentication Request)
5a: The IDP authorization URL is opend.
5b: Because the user hasn't authenticated and has no valid session with the IDP, the URL he wanted to access is stored and the IDP responds with a redirect to its login page.
6: The login page is loaded from the IDP.
7a: The user fills in his credentials and clicks on the login button.
7b: The IDP checks the credentials, creates a new session and responds with a redirect to the stored URL.
8a: The IDP authorization URL is opend again.
(The approval steps are ignored here for simplicity.)
8b: The IDP creates an authorization and responds with a redirect to the callback URL of your authorization server. (See: Authentication Response)
9a: The callback URL is opened.
9b: Your authorization server extracts the authorization code from the callback URL.
10a: Your authorization server calls the IDP's token endpoint, gets an ID and access token and validates the data in the ID token. (See: Token Request)
(10b: Your authorization server calls the IDP's user info endpoint if some needed claims aren't available in the ID token.)
11a/b: Your authorization server queries/creates the user in your service/DB, creates a new session and responds with a redirect to the stored URL.
12a: The authorization URL is opend again.
(The approval steps are ignored here for simplicity.)
12b/+13a/b: Your authorization server creates/gets the authorization (creates access token) and responds with a redirect to the callback URL of your web app. (See: Access Token Response)
14a: The callback URL is opened.
14b: Your web app extracts the access token from the callback URL.
15: Your web app makes an API call.
16/17/18: The API gateway checks the access token, exchanges the access token with an JWT (which contains user infos, ...) and forwards the call.
A setup where the authorization server calls the API gateway is also possible. In this case, after the authorization is done, the authorization server passes the access token and JWT to the API gateway. Here, however, everytime the user infos change the authorization server has to "inform" the API gateway.
This is a very long question. But I believe most can be summarised by answering below,
To my understanding, all the articles and examples I found assume you want access to eg. google calendar, profile info or emails if you eg. login with google,
You do not necessarily use Access token (ID token in some occasions) to access the services offered by token issuer.You can consume tokens by your own APIs. What these Identity Providers (synonym to Authorization server, or IDP in shorthand) is to hold identities of end users. For example, typical internet have a Facebook account. With OAuth and OpenID Connect, the same user get the ability to consume your API or any OAuth/OIDC accepted service. This reduce user profile creation for end users.
In corporate domain, OAuth and OIDC serves the same purpose. Having a single Azure AD account lets you to consume MS Word as well as Azure AD's OIDC will issue tokens which can be used to Authorise against an in-house API or an third party ERP product (used in organization) which support OIDC based authentication. Hope it's clear now
A note on the diagram is that the Authentication service could probably be built into the API Gateway - not sure if that would be better?
If you are planning to implement an API gateway, think twice. If things are small scale and if you think you can maintain it, then go ahead. But consider about API managers which could provide most of your required functionalities. I welcome you to read this article about WSO2 API manger and understand its capabilities (No I'm not working for them).
For example, that API manager has built in authentication handling mechanism for OAuth and OIDC. It can handle API authentication with simple set of configurations. With such solution you get rid of the requirement of implement everything.
What if you can't use an API manager and has to do it yourself
OpenID Connect is for authentication. Your application can validate the id token and authenticate end user. To access APIs through API Gateway, I think you should utilise Access token.
To validate the access token, you can use introspection endpoint of the identity provider. And to get user information, you can use user-info endpoint.
Once access token is validated, API gateway could create a session for a limited time (ideally to be less or equal to access token lifetime). Consequent requests should come with this session to accept by API gateway. Alternatively, you can still use validated access token. Since you validated it at the first call, you may cache for a certain time period thus avoiding round trips to validations.
To validate user details, permission and other grants, well you must wither bind user to a session or else associate user to access token from API gateway at token validation. I'm also not super clear about this as I have no idea on how your DB logic works.
First Appreciate your patience in writing a very valuable question in this forum
we too have same situation and problem
I want to go through ,as images are blocked in our company in detail
Was trying to draw paralles to similar one quoted in the book
Advance API In Practise - Prabath Siriwerdena [ page 269]Federating access to API's Chapter. Definitely worth reading of his works
API GW should invoke Token Exchange OAUTH2.0 Profile to IDP [ provided the IDP should support TOken Exchange profile for OAUTH 2.0
The Absence of API Gateway , will result in quite bespoke development
for Access Control for each API Check
you land up in having this check at each of the api or microservice [ either as library which does work for you as a reusable code]
definitely will become a choking point.]
Creating an angularjs single page application trying to use a RESTful API and I came across a problem that I can't seem to find an answer for. I was trying to prevent session hoping, one user logged in watching the requests figures out his account ID is 13. So he performs the same request but this time alters the request to get info for account ID 14.
So after the user logged in I was setting a session variable to his account ID and was going to strip the account ID out of the ajax requests. I then tried to access the Session from a class inheriting from ApiController. After looking around I realize that storing session information is not very RESTful.
So how would I go about ensuring that one account cannot access another account's information just because they watched the ajax requests and figured out how to manipulate the ajax request?
Is restful not meant to be used with users that need to authenticated and authorized? I was thinking of maybe hashing the IDs or something but I am not sure that is the right approach.
UPDATE:
I have token based authentication working now. But I am still in the dark as to how to prevent someone from fiddling with HTTP request and getting information that doesn't belong to him. For Example, I want to retrieve all the users for account with ID 14.
HTTP Get /users/14
I have a token so I know that the person trying to use the web API at some point authenticated themselves. I can lock it down to roles. But there is nothing stopping this authenticated person form fiddling/hacking with the request and doing the following
HTTP Get /users/58
Now the person has got all of account with ID 58's information. This is information does not belong to account 14 but now he can browse through other people's information.
I need someone of knowing that the request that comes from the browser and says it is for account with ID 14 that it really is account 14. I can put that information in the token but how do I check it in a handler or check it in the ApiController?
The problem you have described is not something unique to REST-based services. In fact, this is one of the top 10 OWASP vulnerabilities (Insecure Direct Object References). You will need to first identify the user and then authenticate the user. For identification, an ID is used, such as user ID. The identifier can be anything you want. After identification, you need to authenticate the user. This is done by authenticating the credential presented to the app, such as password. The identifier and the credential can be any thing, say the good old user name/password, or may be a token or may be an API key. It actually does not matter to the problem on hand. Once authenticated, you authorize the requests based on what the user can do in your app. The authz part is a must regardless of whether you use a token, certificate or what not. Hashing user ID or using some method to hide things is security by obscurity and is not a good practice.
Say, you are using a message handler to authenticate the credential submitted by a user. Once authentication is done you can store the account number associated with the authenticated user in the properties collection of HttpRequestMessage. This is done in the server side and no user can make the system store some random account number. Only the account number associated with the authenticated user is stored in the properties collection. With that, you can now authorize requests. Say, you can write an authorization filter that pulls this account number and compare it against the account number in the URI to determine if the request is allowed or not. By applying this filter against a GET action method, you can ensure only right folks can see right data.
For example, a user with user ID 'abc' and password 'pwd1' makes a GET request to /users/14. First step is, you will authenticate the user ID. If there is a user with ID 'abc' and password 'pwd1' in your store, you will consider the user authentic. As part of this authentication, you can pull the account number associated with the user 'abc'. Say it is 15. You will store 15 in request.properties. From your authorization filter, you can get the account number from URI, which is 14 and compare it against the one in the request, which is 15. Obviously the numbers do not match and you reject the request in the OnActionExecuting method of your filter with a 401.
What I described above is a simple approach. Better one (in terms of extensibility) will be to use claims but it will not be possible to explain all that here. You can get good amount of information related to claims-based identity from Dominick's blog.
Every request should be authenticated. If the credentials provided do not allow the user with account 13 to access data from account 14 then the request will be denied. The trick is to find a way to do authZ quickly.
You seem to be missing the information on how you want to implement authentication. As you correctly noted, using session to keep authentication information is not very restful. Here are the alternatives
Implement your own OAuth provider or use third party (for example
Azure ACS)
Implement STS provider (this is only for soap though)
Implement a custom token system, if you don't want to deal with
the above two. Basic system would take user id, salt it and encrypt with private key - but don't quote me on how secure that would be...
In all the cases, the authentication information is stored in the cookie, similar to session cookie. But it is still stateless.
The standard way on the web seems to be the oauth way, in fact the standard VS MVC template even comes with OAuth consumer implemented out of the box. So the question is, how do you link the oauth token to your internal user ID. That's really pretty simple, as you implement the "registration" step after the new user is authenticated - you keep user ID and oauth token in the database table, to link the two.
That link is quick to retrieve, and can be cached for speed. I have heard some people implement that type of credentials caching for some very big systems (google docs).
I am trying to build an application where a user can specify a URL for a website and my page will go to that URL and grab information. If the URL requires user authentication to access the information, then I want to use OAuth 1.0 to be able to do that.
The problem is, and I see this skimped over in OAuth tutorials, as far as I can tell my application has to already, somehow, be registered with the page I am requesting information from. My understanding is that for any page I want my users to be able to use, I have to go to the page individually by myself and register my application. Once that's done, it will give me a consumer key and secret that I hardcode into my page, and then use those when I am accessing the request URL, authorization URL, and access URL. This is, of course, no good for me because I want my users to be able to specify arbitrary pages to access information on and then provide their credentials to those pages in order to give my app access to the information on them.
Additionally, from what I can tell, there are three URLs that I need to know:
The request URL, which I send my consumer key/secret pair to in order to receive a new, unauthorized request token.
The authorization URL, which I direct the user to with query arguments for the request token and the oauth_callback. The user will be redirected out of my webpage, log in to the foreign site, grant me access, and then be redirected back to the URL specified in oauth_callback with information regarding whether or not they authorized my request.
The access URL, which I send the authorized request token to, expecting to get an access token in return.
And then, once I have all those, I can use the access key/secret pair as a username and password. I store them in a cookie related to the user, and use them henceforth whenever I am access information on the website. On the website's end of the deal, it will look for that information in my request, and if I include it properly then I will be allowed to access whatever of the user's data I please.
Is what I am trying to do - give generic OAuth access to websites - possible, or is it required that I, as the application owner, register my application with the server in order to get OAuth access to it? If it is possible, then how do I get that request URL, authorization URL, and access URL?
It's not really possible. Here's the short list of problems you will encounter:
You need to have application tokens (e.g. your application registered with the resource owner) for all websites. It's not something you can do on the fly
Inconsistent OAuth URL schemes from different resource owners. Twitter has a different URL structure for OAuth than Google does which is different than Foursquare. It's not really possible to figure out the URLs without hardcoding it
Scopes. When you do OAuth registration for many resource owners, you need to specify a scope. How will you know what the scope should be
Goal:
Allow a user to authentication with Facebook into an iOS application which requires access to a protected web service that I'm running.
Assumptions:
There is a native authentication (and registration) system in place for those users that opt not to use Facebook for sign in.
Details:
Assume we want to offer the option for a user to sign in with Facebook without creating a separate account/credential for our system.
Because we support our own native auth mechanism (username and password) we have our own user IDs and issue an authentication token that is used for subsequent interactions after the initial credential validation.
I'm surprised that Facebook doesn't have best practices for this in their developer documentation. All the existing documentation is either assuming you are building FB auth into a website, or a standalone mobile app with no service that requires authentication.
Here's my initial thoughts on how this would be designed but want validation on whether it's correct.
Client pops the Facebook iOS Login
UI User signs in with Facebook credentials and gets access token
iOS App passes access token to our server
Our server talks to FB graph API using access token to (a) validate the token and (b) get the FB user ID for that access token.
e.g. Our server would call https://graph.facebook.com/me/?access_token=XYZ which would return profile info in a JSON object
Assuming it's valid, our server extracts the User ID from the JSON object and checks whether the user already has an account. If so, we issue our own auth ticket to client to use for that session. If user doesn't have an account, we create a new one with the Facebook User ID, assign our own unique UserID and issue our auth ticket.
Client then passes auth ticket back on subsequent interactions that need authentication.
This seems like the right approach to me but not sure if I'm missing something insanely basic and going down the wrong (complicated) path.
I just dealt with this myself, and here's the part that bit me:
In your step 5... It's possible for a user to register for an account with you entirely separate from their Facebook ID, right? Then some other time they log in with Facebook.... And you just created them a second account and lost their first one.
There needs to be a way to be logged in to your web service, then log in to facebook, and capture the association between the facebook ID and the local account.
Apart from that, your plan sounds solid.
Update: Facebook has added a doc outlining such a scenario HERE
Use https to transmit the auth token to your server, as stated by Facebook
Sharing of Access Tokens
Our Data Policies explicitly prohibit any sharing of an Access Token
for your app with any other app. However, we do allow developers to
share Tokens between a native implementation and a server
implementation of the same App (ie. using the same App ID) as long as
the transfer takes place using HTTPS.
One problem I can see with this strategy, is that somebody can give you an access token obtained for a different facebook app. As far as I know, there's no way to verify that the access token is for your application, so you'll just go on and use it.
It doesn't sound very harmful, though. Generally people/apps try to protect the access tokens, rather than sharing them.
One possible exploit of this would be, for somebody to create their own site or mobile app, obtain access tokens for their users and try to authenticate them, using your API. If this succeeds (the user is has a facebook account in your site), the malicious site will be able to use your API impersonating the user.
It's a bit of a long shot, but I think it could work.
Edit: It looks like there is a way to validate the access token after all. See the answer by #Daaniel on question Get application id from user access token (or verify the source application for a token).
your solution totally works.
Maybe an alternative: why not just get the email on the client from the initial social service request and send to your web service? The web service could just store the email, and maybe a social_provider as well. I understand that your web service will not be able to validate where the email came from, but isn't there a high-trust relationship between your web service and your client? If there is, seems like you can depend on the email coming from the right place. Someone please let me know what obvious thing I'm missing that makes the email-based approach silly...