Downloading from Google Docs using an Uri containing access_token - oauth-2.0

I'm creating a viewer app for Windows Phone 7. The app already handles the OAuth2 stuff and succesfully browses Google Doc's folder structure.
I use Google Documents List API 3. BTW browsing works perfectly without using request headers, instead I append the access_token to the request Uri.
Now the app needs to show files to the user, if possible without downloading them first. This means that I want to set the UI's Image.Source to the Uri of an image, the UI's MediaElement.Source to the Uri of a video and the BackgroundAudioPlayer.Track.Source to the Uri of an audio file. Obviously I can't use request headers in this scenario.
However it seems that simply appending the access_token to the download Uri doesn't work. The UI elements fail with generic error messages, and if I manually try with a web browser (which isn't logged in to Google) it shows an empty screen, a 401 error or it redirects to Google's login page.
Is it possible to download/stream a Google Data entry just by defining the Uri? If yes, what does the Uri need to look like?

Support for authorization using the access_token URL parameter has not been allowed on purpose for security reasons. Basically if a user would be to open a malicious file on a browser (e.g html containing some Javascript would suffice) the malicious code on the file could steal the access token in the URL and send it to a third party bad guy.
To access the file you need to authorize using "Authorization" HTTP header. Simply add an HTTP header to the request which is like:
Authorization: Bearer access_token_here

Related

OAuth 2.0: why is the access token or temporary code placed in the in the URL fragment (after the #) instead of in the query string?

I am learning OAuth 2.0.
In both code flow and implicit flow (response_type = code or token). The temporary code or access_token is placed in the URL fragment (after the #) instead of in the query string.
According to this doc: https://developer.okta.com/blog/2018/05/24/what-is-the-oauth2-implicit-grant-type:
If the user approves the request, the authorization server will redirect the browser back
to the redirect_uri specified by the application, adding a token and state to the fragment
part of the URL.
For example, the user will be redirected back to a URL such as:
https://example-app.com/redirect
#access_token=g0ZGZmNj4mOWIjNTk2Pw1Tk4ZTYyZGI3
&token_type=Bearer
&expires_in=600
&state=xcoVv98y2kd44vuqwye3kcq
Note the two major differences between this and the Authorization Code flow: the access token is returned
instead of the temporary code, and both values are returned in the URL fragment (after the #) instead
of in the query string. By doing this, the server ensures that the app will be able to access the value
from the URL, but the browser won’t send the access token in the HTTP request back to the server.
What exactly does it mean by
the server ensures that the app will be able to access the value from the URL, but the browser won’t send the access token in the HTTP request back to the server.
?
Of course the code/ access_token value is accessible from the URL.
The Auth server builds up the url and put it in location header of the HTTP response, which is sent back to the user's web browser. The web browser then take values from the response, and send new http requests to the application instead of the Auth server. So, of course the user's web browser is not sending HTTP request back to the server.
It has nothing to do with where the access token is placed in the response (from Auth server back to the user's web browser). The web browser simply starts talking to the application again instead of the Auth server.
This explanation just does not make much sense to me.
The code flow returns an authorization code to the browser in the query string. You then make a POST request to swap the code for tokens.
https://www.example.com?code=xxx&state=yyy
Implicit flow is now deprecated since it can reveal tokens in the browser history or server logs. It dates back to when browsers did not have CORS capabilities to make cross orign POST requests to the Authorization Server.
Data in client side hash fragments does not get sent to servers and the implicit flow used this as a partial mitigation for sensitive data. Eg the zzzz below does not get sent to the web server if you type this in a browser.
https://www.example.com#zzzz
If you are new to OAuth and OpenID Connect, start with code flow + PKCE, and understand these messages.
SWAPPING THE CODE FOR TOKENS
This is often done via a back end component that completes the flow, so that a client secret can be attached (a browser cannot keep secrets). This back end component can then do either of these:
Return access tokens to the browser
Issue secure cookies to the browser
Once done, the front end has a credential with which it can call the main back end (eg APIs), so that the back end knows the user identity.
CODE EXAMPLE
In 2021 the cookie option is considered more secure, but it also requires a more complex flow. All of the complexity involved originates from the browser being a hostile place to execute code - there are lots of security threats there. Here is some example code that uses cookies:
OAuth calls from an SPA
API calls from an SPA

Find out who invited my bot the server using OAuth redirect uri

Before someone marks this question as duplicate,
Yes I know audit log is a thing.
No I won't use it because it requires permission.
Yes it's easier to find out server owner
No I need to know exactly who invited my bot
I want to:
Find out who invited my bot the server (user-guild id pair) using invite link redirection.
I read about the OAuth2 API but didn't quite undertstand it due to my lack of background knowledge.
All I understand is that bot invite links can have redirect uri,
and some infos are transfered to it after authentication.
Is it possible to get user/guild id from this?
I tried:
Setting up http server using python -m http.server,
add my IP to redirect uri list in dev page & generate a invite link containing redirect to my IP.
But I didn't get redirected to my http server after inviting my bot using that link,
and nothing got printed on the http server console either.
Things to note:
A. Don't reveal your client secret or your bot token for any purpose. If you do so, immediately regenerate them from the developer portal.
B. Code and token have different meanings in the answer below.
C. This is not for absolute beginners and you are expected to have a general understanding of web requests(specifically GET and POST requests). You might also need to host the site handling redirect URL.
D. This does not cover security issues in any shape, way or form.
In the bot tab of the developer portal, enable the REQUIRES OAUTH2 CODE GRANT option. This prevents the bot from joining a server unless step 4 is completed.
Then use the OAuth tab to generate an OAuth URL with identity and bot scopes. This is important to get user info in step 5.
When someone visits the URL, logs in, and selects a server, they are redirected to your redirect URL. This URL receives a single-use code as URL parameter ie the URL will be <base_url>&code={code}<other stuff>. It is up to you (and probably outside the scope of any SO answer; google is your friend here) to set up a web server and handle requests.
This code can then be used to get a token. This link explains how to exchange code for token. It involves sending a post request with your application's client id and secret. Both are available from discord's developer portal. The response will also have information about the guild along with the token in fields "guilds" and "access_token" respectively.
Send a get request to https://discord.com/api/v9/users/#me with a header containing Authorization: Bearer ${token} where the token is obtained in step 4. The response is in JSON format and contains user data specified here. Note: The link above is for the latest API version v9 which may change in future versions.
Edit:
It is possible to manually modify the URL to remove identity scope from URL. The bot would still join the server as long as you make a request to exchange the code for the token. In this case, the request to /users/#me would fail and you would have no access to the user object. It should be easy to make the bot leave the server if the request fails with the status code corresponding to unauthorized.

OAuth2 with Hash query string, Imgur API

I'm updating my desktop app, an Imgur client, for the upcoming deprecation of code/pin auth methods, by using a local web server to catch the redirect_url from the browser after the user authorizes access to the app. So I launch the URL in the browser, the user accepts, then Imgur redirects to
http://localhost:7710/myapp?state=auth#access_token=....&expires_in=
etc
but the browser cuts the URL at # so all the variables are missing, and my app only receives "state=auth"
from Imgur's API docs:
The response_type Parameter token: This authorization flow will
directly return the access_token and refresh_token via the redirect
URL you specified during registration, in the form of hash query
string parameters. Example:
http://example.com#access_token=ACCESS_TOKEN&token_type=Bearer&expires_in=3600
The code and pin response types have been deprecated and will soon no
longer be supported.
Imgur returns an access token to your application if the user grants
your application the permissions it requested. The access token is
returned to your application in the fragment as part of the
access_token parameter. Since a fragment (the part of the URL after
the #) is not sent to the server, client side javascript must parse
the fragment and extract the value of the access_token parameter.
Clearly they haven't thought this through for desktop applications, or am I missing something?
Imgur stuff looks non standard, since response_type=token is a basic version of the implicit flow, which used to be the solution for single page pps.
These days all UI based flows should use Authorization Code Flow (PKCE) and response_type=code.
Since your app is acting as a (loopback) web server it will not receive the hash fragment parameters, which are only available to JavaScript code running in a browser.
One option that would enable you to get the full URL would be to login via the system browser and to use a Private URI Scheme to call back to the app.
The above link is a visual blog post to explain how this works, in case it is of interest.

Add headers to a link in angular

I have an angular app that I need to redirect outside to a server side html page, so I thought I could just use a standard <a> tag with target='_self' to redirect the angular app to my server side page. This actually works fine, however, I have a rails backend that checks for auth token before serving up any content.
This requires a auth token to be sent in the header of the http request which I am setting in a cookie, and angular grabs automatically with the $http service for ajax requests, but I can't seem to get the same thing to happen on a standard link.
Can/How do you add an auth token to a normal link before it is sent off?
When the browser is making the HTTP request and not your JavaScript code, you cannot add a custom header with your token value. See Adding http headers to window.location.href in Angular app for a similar question.
However, if this value is already being sourced from a cookie, can your backend just read that cookie value (or use some filter in the http request chain to transfer the cookie to a header)?

Google OAuth 2.0 Callback URL

I have an iOS application which authenticates with Google's servers via OAuth 2.0. I have just one problem, my app doesn't seem to respond to the callback URL. I have set the callback URL correctly in my code but no response.
I was just wandering if anyone knows how to change the callback URL on the Google OAuth API Console because right it is some random URL which doesn't seem to work for me:
urn:ietf:wg:oauth:2.0:oob
You can use the oob URI with an embedded view, or you can rely on the user to copy and paste the code.
But on iOS you have a better option, you can use a custom scheme based on the bundle id (or on the client id):
https://plus.google.com/111487187212167051233/posts/AztHNnQh7w6

Resources