I'm currently working on a project for content partners network. I would like to provide Login with YouTube feature, as well as other stuff.
So I'm currently implementing oAuth2 authentication, and when that succeeds I get access_token and refresh_token, but no identification (could not know who do tokens belong to, just by having them).
Is there any kind of global YouTube/Google User ID within https://www.googleapis.com/auth/youtube.readonly scope (or any other scope) that I could get with my tokens?
All you need to do is a channels->list call with "mine" = true. That will give channel id and all the information about user(channel).
GET https://www.googleapis.com/youtube/v3/channels?part=id%2C+snippet%2C+brandingSettings%2C+contentDetails%2C+invideoPromotion%2C+statistics%2C+topicDetails&mine=true&key={YOUR_API_KEY}
I am not familiar with this API, but the etag should change if the content at that URL changes, and could change at any time even if the content has not changed.
https://developers.google.com/youtube/2.0/developers_guide_protocol_profiles
To request the currently logged-in user's profile, send a GET request to the following URL. Note: For this request, you must provide an authentication token, which enables YouTube to identify the user.
https://gdata.youtube.com/feeds/api/users/default
You kinda sorta might be able to do this with a cookie.
1) you present your page with a set-cookie that redirects to the oauth2 google page.
2) user auths with google sends a redirect to the browser going back to your page.
3) the browser is redirected to your redirect page with your cookie.
Not great, but I think it should work.
Related
I'm new to OAuth2 and I'm trying to understand the whole flow of things. For context, I'm thinking of making a web dashboard where users log in via Discord's OAuth2 API.
This is how I think the flow works based on my understanding so far:
User goes to my site and clicks a login link
My site redirects them to Discord with my client ID and a redirect URL #1 in the query string
Discord redirects them back to my site at redirect URL #1 with an authorisation code in the query string
My site takes this authorisation code and along with my client ID, client secret and redirect URL #2, uses all these to fetch an access token and refresh token from Discord
If I do get an access token, that means the user is now "logged in" (authorisation code worked)
My site finally redirects the user to a page and is now free to send requests to Discord's API with the access token, while saving the access token and refresh token. Just for example, say the page states their Discord username
I'm learning from this guide, and what confuses me is this code snippet from the guide. At line 5, it provides the redirect URL #2 mentioned above, in the query string. I'm not sure what it's for.
Also, I'm not very sure how to continue once I have the access token. If multiple users log in, I'd have multiple access tokens on hand. Say a user wants to access the page again, how do I uniquely identify them and know which access token to use to send requests to Discord's API? (for this example, the request would give me their username which I'd display on the page)
Yeah, I probably got a lot of concepts wrong. Any clarification would be greatly appreciated!
Edit: I've done more research into this, and found a much better guide here.
For my question about the second redirect URL, the examples in the official documentation specify a redirect_uri when doing both an access token and a refresh token exchange. However, this new guide makes do without for their access token exchange. Perhaps they missed it out? As this other stack overflow question says:
As an added measure of security, the server should verify that the redirect URL in this request matches exactly the redirect URL that was included in the initial authorization request for this authorization code. If the redirect URL does not match, the server rejects the request with an error.
I suppose this means that after the first access token exchange, any refresh token exchanges or straight up API requests with access tokens need to match the original redirect_uri of said first access token exchange. So I should use one and only one redirect_uri, and the refresh token exchanges/API requests do not actually use the redirect_uri, rather it's used for further security.
As for the whole login procedure, it seems I have to link the access & refresh tokens I obtain to a user session, and for that I'll look into using this passport strategy, passport-discord. Then, once the session expires, I'll discard the two tokens, and they'll have to click login again, but I can make use of this prompt option:
prompt controls how the authorization flow handles existing authorizations. If a user has previously authorized your application with the requested scopes and prompt is set to consent, it will request them to reapprove their authorisation. If set to none, it will skip the authorization screen and redirect them back to your redirect URI without requesting their authorization.
From there I think I'd just store the new access and refresh tokens associated with that user.
I'd really appreciate if any mistakes in my thought process could be pointed out!
Your summary seems good to me Mr Cloud - worth clarifying whether you are developing an SPA or (old) web app with a server side. Most commonly the first is cookieless, whereas the second stores a refresh token in a cookie. A key thing is to understand what the OAuth message workflow looks like. For SPAs and APIs this write up of mine may help you clarify what you want: https://authguidance.com/2017/09/26/basicspa-oauthworkflow/
Happy to answer any follow on questions ..
You can use the implicit grant to use with SPA
https://discord.com/developers/docs/topics/oauth2#implicit-grant
I'm implementing OAuth (using rauth) and will be giving JWT tokens (using flask-jwt), javascript frontend (Angular1). I have done it for classical cookie/session based app. It works. Now I want to do it with JWT tokens.
If I understand correctly, user is redirected to provider (ex. Google), login into account, my server and provider do the magic, then provider redirect user back to my page. Now I got user profile and that ends the OAuth part. With normal session you give user cookies and the rest of stuff for setting up session, then redirect him to home page.
This is where I'm stuck. Is there any good practice how to give user JWT token after provider send him back? Give it to user as cookie on redirect to home page? Put it in header? As far as I know I need javascript to save token into LocalStorage/SessionStorage.
At the end of the day, the user will be redirected back to our app where a page now needs to be rendered. The only option I see is to return the JWT as a cookie because response headers aren't accessible in Javascript & the only other place would be to embed it in the DOM which would open it up to CSRF attacks.
When the browser is redirected from the OAuth provider it will only have an access code which can be exchanged for an access token on the server side. But best practice says you need to keep that access token secret (not pass it back to the browser).
There is a lot of debate about JWT's in cookies vs local/session storage but in this use-case I don't see any other option than to use cookies. All the use-cases I have seen that describe using browser storage assume an XHR request is being made to obtain the JWT. But this isn't an option in an OAuth flow because the entire browser has just been redirected back to our app.
I don't see another option (for the OAuth use-case) other than keeping the JWT in a cookie to be used for future API calls. But maybe I'm missing something.
Before passing control to Facebook auth, you can initiate a socket connection to your API, then probably show a loading status in your app. Afterwards let Facebook do it's thing. When it succeeds, it posts data to your backend. Your backend does it stuff and passes the JWT to frontend using the socket it created earlier. This seem like too much work & could come with extra bugs if you don't do it correctly.
const jwt = require("jsonwebtoken");
module.exports = {
signToken: function (payload) {
return jwt.sign(payload, "secret");
},
};
Goal
Fetch a company's updates save them locally in a background task
Problem
This should be done as a backend service without any real user interaction. We could provide a user account to use, but the authentication is a problem: There is literally no one to answer the OAuth redirect and there is no public redirect URL to configure, since it's a background service.
Is there any way to access the API without having a redirect URL or a real user?
You can get an initial access token in a regular front end flow, for you as the app developer i.e yourself as the LinkedIn user. Once you've got that, you can store it in the backend and use it for 60 days to get access to the LinkedIn APIs.
After 60 days you need to refresh the token as documented in:
https://developer.linkedin.com/documents/handling-errors-invalid-tokens
Unfortunately LinkedIn does not (yet) support an autonomous refresh flow where your app can get a new access token by presenting a refresh token on a backchannel. So the developer will have to refresh the access token by a manual login every 2 months.
Well, it is still all HTTP and HTML, so in fact there is no real reason to show the OAuth dialog to a user, as long you can strip out the necessary parts in the HTML authentication dialog and send a valid response back to the server, using the username and password from the user (which you can obtain from him, or save it yourself in a config file if it is you).
Note that there might be a legal issue if LinkedIn demands you to actually show the dialog, beside that, there is no technical need.
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.
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