Cognito OAuth2 access code handling with a desktop app - oauth-2.0

I have a command-line app that I want to authenticate against AWS Cognito using OAuth2 with access code flow and hosted login UI. For the similar case, Google Cloud docs explicitly recommend using http://localhost:N redirect URI, so that the application can handle the access code after authentication:
This authorization flow is similar to the one used for web server applications. The main difference is that installed apps must open the system browser and supply a local redirect URI to handle responses from Google's authorization server.
However, with Cognito localhost URIs are only allowed/recommended for testing purposes:
One alternative solution would be using an "out-of-browser" URI urn:ietf:wg:oauth:2.0:oob to display the access code in the browser and make the user copy-paste it to the app, but Cognito doesn't seem to support it.
Currently I am leaning towards running a custom OAuth2 callback handler that would only tell the user to copy-paste the access code, but I don't find it really friendly from the Cognito side.
So, the question:
What's the recommended way to authenticate desktop / command-line apps with Cognito with minimal user interference?
What can go wrong if I ignore the Cognito's recommendation about the localhost redirect URI?

LOOPBACK URI
In a desktop app you can use localhost HTTP URLs to receive the authorization response, and that is one valid technique.
The Cognito warning is about using localhost URLs for web app responses, which of course is only suitable for a developer PC.
You can ignore the warning when using loopback desktop apps.
OUT OF BROWSER URI
This was used a few years ago to read an authorization response from a web view and is no longer recommended in OAuth for Native Apps.
PRIVATE URI SCHEME
The second valid rechnique is the option I prefer, since it feels more integrated. It involves receiving the authorization response via a URL of the following form, and registering the scheme with the OS to point to your app:
com.mycompany.mydesktopapp:/callback
RESOURCES OF MINE
If it helps, I have a couple of desktop samples / blog posts that use Cognito. You can run the samples on your PC, to see which you prefer:
Loopback URI
Private URI Scheme

Related

Google Drive OAuth – Will my app get verified if my redirect URI is localhost?

I am writing a web app that makes use of the Google Drive API and that I plan to distribute for users to run locally.
I am planning to go through the lengthy OAuth verification process but wanted to ask first whether having localhost as the redirect URI would be allowed. I know that when the app is in testing, it's fine, but then I have a limit of 100 users (same as if the app is unverified). So I need to publish.
I see here in the documentation that localhost URI's are exempt from the HTTPS scheme. However, I'm still unsure of whether the localhost URI is allowed for verified apps. Does anyone know or have a link to the documentation that explicitly says this?
I am writing a web app that makes use of the Google Drive API and that I plan to distribute for users to run locally.
Users would not normally run a web application locally. Web applications should be hosted on a web server. Web client credentials can not be verified and run in production using localhost as a redirect uri.
Have you considered an installed application instead? Desktop apps will run on the users machine. And you will not have a redirect uri issue as the standard redirect uri for installed applications https://127.0.0.1
I am planning to go through the lengthy OAuth verification process.
If you are giving this application as in the source code of the application to other users, you don't need to verify the application. You can not give others your client id and client secret, as part of the TOS you agreed to when you created your project, you agreed not to share it. You will need to instruct the users of your app on how to create their own project and verify it.
See: Can I really not ship open source with Client ID?
I see here in the documentation that localhost URI's are exempt from the HTTPS scheme.
This is only for installed applications, its not going to work for web applications. and it wont work for production apps.
There is actually another link you should check Use secure redirect URIs and JavaScript origins
This page states that you cant use http and you will normally get
documentation conflict
as there seems to be a conflict between Redirect URI validation rules and Use secure redirect URIs and JavaScript origins I have sent an email off to a contact on the Oauth team, to see if we cant get the documentation clarified.

oauth2 openid connect javascript (electron) desktop application

What is the correct oauth2 flow for a desktop application? Besides a desktop application I have a SPA Web GUI which does use the Implicit flow. There it does not matters if the client Redirects after 3600s to the IdP to issue a new Access token.
But the desktop application needs to be running 24/7 or could be running 24/7. So it needs to automatically refresh the access token via a refresh_token. But since the implicit flow does not provide refresh tokens it is probably the wrong flow for a desktop app, isn't it?
I guess I need the auth code flow, which does provide a refresh_token. But authentication requests needs a redirect_uri. Let's say I want to use Google as my openid provider. With google it looks like I can't register client credentials with a custom URI scheme (https://developers.google.com/identity/protocols/OpenIDConnect). What does work is to register for example http://localhost:9300, which theoretically could be handled by the app.
A
Whats the correct oauth2 flow for a desktop app to receive a refresh_token?
B
Can I catch the redirect_uri via a custom URI scheme without using the implicit flow (Google IdP)? It is way easier to listen for a custom uri scheme than listening on a local tcp port.
C
This is more a general question. Usually desktop apps are public apps, so I should not include client_secret right? So the only flow which would be left is the implicit flow. But how can I renew access tokens according to specs without bother the desktop user every 3600s?
In my case I could publish the app locally so not public, but how is it for a public app?
A - Authorization Code Grant
B - Not sure here, You can register a Custom URI Scheme
C - Not enough information provided.
Are you using the AppAuth libraries? If so you SHOULD use PKCE and then additional security measures for the refresh token should not be necessary, on the assumption that the client never sends the refresh token with anyone other than the IDP over a secure connection.
Does this help?
A: Yes use the code grant
B: yes use a custom scheme. In your case you should use the reverse of your client ID. e.g. com.googleusercontent.apps.123 is the reverse DNS notation of the client ID. Register your client as "Other" in the Google developer console.
C: Yes, it should not include the client secret. That is why you don't need to send the secret for native clients ("Other") when exchanging the code for a refresh token. Just leave that field blank and it'll work.
As suggested by jwilleke, please use an AppAuth library if it is available for your use case as it'll also handle some of the security issues (PKCE).
For native apps (Desktop), you can follow OAuth 2.0 for Native Apps. But this is still under review and you can refer the latest draft from provided link.
With this flow, you can use authorisation code flow to obtain both access token and a refresh token. Refresh tokens should solve the UX related issue when it comes to extended app usage (24/7 and beyond).
According to this working document, there are strict guidelines on client authentication. Section 8.5 discuss about them. As it says client credentials are not recommended
For this
reason, and those stated in Section 5.3.1 of [RFC6819], it is NOT
RECOMMENDED for authorization servers to require client
authentication of public native apps clients using a shared secret
Also as nvnagr has mentioned in his answer, PKCE [RFC7636] is a must to have for native public clients.

How do I authorize only my own mobile apps to call my rails 4 api?

I have a web app that exposes an api using devise_token_auth. I build multiple mobile apps that talk to different facets of this web app over https. They use devise_token_auth to get an access token, and then the access token is used in future requests.
I want to avoid the case where others create their own mobile apps that talk to my web backend.
When a call is made from the mobile client, it uses a user and password who has already signed up on my server to get an access token. How do I preclude others from creating their own mobile clients?
Option 1: I could create a secret api token, and use it on the client and server, where mobile client passes in the api token and the server only accepts the requests containing the api token.
Problem with option 1: anyone who sees the request on the wire can now create a similar request with the api token, and use the api token to make the same call.
Option 2: I make my web server an oauth server, where my app uses oauth to authorize client requests only for my own api user, and rejects other requests.
Problem with option 2: I don't know enough about oauth to know if it works this way, and how to implement this in addition to devise_token_auth - this effectively means two credentials are checked on the server - the oauth verification of the api user, and the devise_token_auth verification of the actual user.
I did look at this and this related questions, but they are not exactly my scenario. The recommendation in those threads seems to be a) that https + basic auth is enough and oauth is unnecessary, and b) blocking ip addresses that are unauthorized (Problem: I don't know how to detect which ip address is my mobile app users' and which is someone else's). c) Another insight from those threads is that if I stored some private secret key in my mobile apps to use to identify the app, they are likely going to be exposed since mobile apps (at least on android) are fully reverse-engineerable.
Any suggestions on how best to design/implement this? Is just https + basic auth sufficient?
I would be happy to share any code (since SO usually expects code in the question) - but honestly don't know what code to share here.

OAuth2 breaks security for desktop apps?

Currently in the process of moving from OAuth1 to OAuth2 in a desktop application for a web service (Imgur), I've been baffled by the OAuth2 specs. Apparently it breaks all the security OAuth1 provided, according to this doc http://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified and by looking at different services docs regarding OAuth2.
With OAuth1 you could use a URL to the service where the user would grant access and a PIN was displayed to copy/paste in your app, which was really nice security in the sense that the user never grants their login/password to the app, and can revoke the given access to it at any time through the service's website.
Now with OAuth2 they left this scenario out, forcing the app to request the user's login/password, unless the app makes their own script in their website to receive a token from the service after granting access (then have the user copy/paste it from your website)
Am I missing something here?
Desktop applications can and should use a user agent (browser) to do OAuth and that is described in the OAuth 2 spec under "Native Applications". The flow you described is meant more for devices with limited input capabilities like a gaming console, printer, camera, etc.
AFAIK, the device flow was in the early specs of OAuth 2, but was omitted at some point. Some API providers like Google have implemented limited support for it regardless.
Native applications are the way to go. See the ["Native Applications"][1] section of OAuth 2.0 RFC. The native applications are not intended to store passwords. If you want to avoid entering of credentials directly in the app (even within a browser control), you may do the following from the OAuth 2.0 native application:
Launch the default browser with the authorization endpoint.
Implement a simple web page for your redirect URI, which picks the authorization code and shows it to the user.
Ask the user to copy the code and paste it back in the native application.
Alternatively, the spec suggests that you leverage the URL redirection scheme of the native platform to bring back the original application. You may check iOS and Android's "URL Scheme" capabilities. Unfortunately, neither of these platforms guarantees uniqueness of the URL scheme, hence the authorization code may be hijacked by another rogue app, which is activated on the same URL. I have filed an iOS bug for that.
[1]: https://www.rfc-editor.org/rfc/rfc6749#page-52

OAuth for Desktop apps?

i wonder how do desktop apps without any domain names use oauth? or is it not supposed to be used this way? if so what do i use? say for tumblr they have an authentication api so i will have to put the username and password in the url/query string?
i am thinking of using WPF/Adobe AIR. how does something like tweetdeck work?
I've been puzzled by the same question about lack of domain or app url, but it turns out redirection is not the only possible way to complete OAuth authentication process.
I.e., when webapp requests access it provides callback url: the one user will be redirected to when process is completed. That's how webapp know that everything's done.
But you can't redirect to application on user's machine. Thus, there's another way: upon successful authentication server presents special code to the user. Then user copies this code and provides it to application.
You can see both ways described in specification draft.
Also, here's an example of this authentication flow with twitter.
It looks like it may be possible, see googles docs on the subject:
https://developers.google.com/identity/protocols/oauth2/native-app
For a desktop app where a user needs to authenticate himself, you will usually want to use the Authorization code flow.
The approach goes roughly like this:
setup a temporary webserver that listens on the loopback interface
present the login page to the user (either in an embedded browser control or an external browser), with the URL of your temporary webserver as redirect_url
upon successful login, the user will be redirected to your temporary webserver and you can obtain the access code from the code query parameter
Using the access code, you can obtain a token and start making requests using it
Shutdown the temporary webserver
Please note that you will have to allow localhost as redirect URL in your identity provider, in ordrer for this approach to work.
For further details, please take a look at these sample apps from Google.
You should start by reading about getting started with OAuth. Eventually, even a desktop application will open a browser window to authenticate the user - TweetDeck and other Twitter clients do this, as you've probably noticed.
Tumblr, in your example, doesn't use OAuth but rather basic authentication that is being performed via simple HTTP web requests.
Twitter doesn't want users entering their credentials into your application. So at some point the desktop app will need to open a browser window through which Twitter can authenticate their users and return an access token representing the user. From that point the desktop app can use the access token to represent the user in all subsequent API calls to Twitter.
In a desktop environment you have another way to get the token, the browser open url itself.
the OAuth2 server will redirect the users browser to the Redirect URL with the token as a query parameter, so if you control the browser used, you can read the the token directly from the url that the user was redirected to.
Graphical libraries like GKT+ have integrated options to create mini browsers that the user can use to authenticate, and it automatically return the token to the app, but other options are possible, like reading Firefox url for example.

Resources