11

I'm working on an command line utility that requires access to a backend server over a REST API.

I'm trying to avoid implementing my own authentication mechanism and use one (or more) of the public auth services (like google, Facebook, amazon).

I am trying to make the client accept credentials and authenticate against the authentication provider and do that without asking the user go open a web browser and provide back a token. The client will be open sourced in order to avoid trust issues (i.e. the user credentials are not sent to my backend server).

I am not interested in authorization, I only care of authenticating against my backend server without having the user keep yet another set of credentials (and without sending the user credentials to my backend server).

How can I have my client authenticate with the auth provider and get a token to communicate back with my server without having the user use a web browser?

dsalama
  • 242
  • 1
  • 6
Pavel Georgiev
  • 111
  • 1
  • 4
  • Side note: "_I'm trying to avoid implementing my own authentication mechanism and use one (or more) of the public auth services._" This is a fantastic idea. Good on you. I don't quite get why you need to have authentication, unless I'm misunderstanding what you're making. Another side note: "_The client will be open sourced in order to avoid trust issues_" There is still zero trust, because who says that the program you're running is the one whose source you're displaying? For all the end user knows, you have some extra lines of malicious code in the prod version – Nic May 02 '15 at 23:01
  • The reason I need authentication is because the server is going to be exposed to the world, I need to restrict access to certain users only. The client will most likely going to be in an interpreted language, so users can view the code, download the code from github or even write their own client (which will be encouraged) since the interface to the server is also going to be open sourced. – Pavel Georgiev May 04 '15 at 17:15
  • Ah, so I entirely misunderstood what you're making. Alright then. Also, it might be possible to return one file to external requests and another to internal ones, so your code could still be malicious. – Nic May 04 '15 at 19:14
  • I won't post that as an 'answer' since I've found this post trying to validate my understanding, but isn't the Password Credentials Flow exactly what you're looking for? – Radim Vansa Dec 01 '20 at 14:30

1 Answers1

2

I realize you said "not open a web browser", but what about if that browser is on another device (e.g. their mobile?).

If that is acceptable, you can use the OAuth 2.0 for Devices approach, whereby you present the user a short alphanumeric code, which they enter on http://google.com/device to authenticate the request from another device. This OAuth flow is designed to work in environments which don't have browsers (like a command line).

To see a demo of this authentication flow in action, visit the YouTube TV site, press the ← key on your keyboard, and select Sign In.

It's also easy to try out yourself – create a OAuth client in the developers console (of type "installed application" -> "other"), and follow the curl examples in the docs (be sure to replace the demo code in the token request with the device_code received from the initial request to the code endpoint). Decode the resulting id_token using any of the example JWT decoders, like this one.

In your case, you should request the profile scope, which will return an id_token in the response to your token endpoint call, from which you can extract the user's Google profile id (the id token's sub field).

William Denniss
  • 16,089
  • 7
  • 81
  • 124
  • Thanks for the suggestion. I had a look at the device approach, but it would not be my first choice - I would still prefer a way where the user can provide the authentication credentials in a single step (which is also suitable for automated environments). If I fail to find a way to do this, then I can use an approach which requires a one time operation to establish trust (in which case either a browser or a device will be acceptable) and then use that token for further communication. – Pavel Georgiev May 04 '15 at 17:21
  • Regarding the scope - is the 'profile' the best approach if I don't want to authorize with any of the G services. Is the profile id the user's email (or something else that I can use as an unique token to keep in my user database)? – Pavel Georgiev May 04 '15 at 17:26
  • 1
    Correct, `profile` is the best scope if you just want authentication, and no authorization, add the `email` scope if you also want the user's email address. You should use the `sub` field of the ID Token as the unique Google user identifier. – William Denniss May 04 '15 at 18:13
  • 1
    The linked OAuth 2.0 for Devices documentation suggests that CLI programs running in an environment with access to a browser instead use [OAuth 2.0 for Mobile & Desktop Apps](https://developers.google.com/identity/protocols/OAuth2InstalledApp). – phs Aug 31 '17 at 00:15