3 releases
0.0.3 | Sep 28, 2018 |
---|---|
0.0.2 | Sep 27, 2018 |
0.0.1 | Sep 17, 2018 |
#10 in #oauth-token
31KB
508 lines
Olaf2 CLI Authentication Helper
This is a pretty hacky proof of concept to enable convenient authentication of command line applications using a third party OAuth provider.
For more detailed information, see the documentation.
This also doesn't fully work via crates yet, since we depend on the unpublished github version of oauth2-rs.
Also, this was an experiment in using edition 2018, so things may not properly work.
Hopefully though there are some useful techniques/concepts here that can be borrowed.
lib.rs
:
Olaf2 is a library for conveniently authenticating command-line applications using OAuth 2.0 via a proxy server.
Note that OAuth 2.0 is an authorization (authz) protocol, not an authentication (authn) protocol. OpenID Connect is designed as an authn protocol on top of OAuth 2.0, but is not widely deployed.
Olaf2 provides an form of authentication by authorizing the proxy server to retrieve the end-user's identity. For example, using the Github provider, the proxy receives a token which can be used with the Github API to recover the user's github account name.
Olaf2 can also be used to recover the OAuth 2.0 token for accessing resources locally.
A lot of the heavy lifting is done by the oauth2-rs crate.
Terminology
The "Server" refers to the OAuth 2.0 authorization server, and is implemented externally to Olaf2. We provide some preconfigured servers to connect to.
The "Proxy" refers to the OAuth 2.0 client, which receives the authn and authz from the Server.
The "Client" refers to the command line application, which becomes authenticated by running the protocol.
The "User" refers to the OAuth 2.0 resource owner, who wishes to authenticate the CLI application, and visits URLs in a browser.
Usage
Proxy server
Obtain client id/secret values by visiting the auth provider website.
Configure the proxy, for example:
# in proxy_config.toml
client_id = "deadbeefcafe1337"
client_secret = "somesecretvalue"
port = 8081
proxy_url = "http://localhost:8081/"
oauth_provider = "Github"
scopes = ["read:user", "user:email", "read:org"]
welcome_redirect = "http://localhost:8080/"
Run the proxy with
use olaf2::*;
use toml;
// the lazy way to load the config...
let toml = include_str!("proxy_config.toml");
let config: proxy::Config = toml::from_str(toml).unwrap();
proxy::run_with(config, |token| {
// This simple function prints the access token and
// returns it to the client
let secret = token.secret().to_string();
println!("Received token: {}", &secret);
Ok(secret)
});
In this example, we are creating a session token handler
which simply prints the access token and returns the String
to the client.
On the other end of the connection, we need to tell the client
to accept a String
.
Client
Simply run the client with:
let secret = client::authenticate::<String>("http://127.0.0.1:8081");
println!("Secret: {}", secret);
Note: the proxy server returns a String
from the closure, so we
specify the same type parameter for authenticate
.
Details
The protocol flow works as follows:
- The
Client
starts a local HTTP server on a random port. makes a get request toproxy_url
, including the port number and a random nonce.
The Proxy
server returns an OAuth 2.0 authz request URL.
-
The
User
visits this URL (theServer
) ito authorize the request. This includes a URL redirection back to theProxy
. -
The redirected request should contain the authz code from the OAuth 2.0
Server
. -
The
Proxy
exchanges the authz code for an access token. This token can be used to accessServer
resources (depending on the scopes requested). -
The
Proxy
determines the identity of theUser
by using this access. TheProxy
responds to theUser
request by serving an HTTP page (a welcome page) which should include a request to the local HTTP server with the final session token. -
When the
User
browser makes a request to the local HTTP server being run by theClient
, the session secret is captured, and theClient
can continue in authenticated mode.
Diagram
4. Exchange authz code from (3)
Use token to verify identity.
to get an access_token.
(e.g. GET /api/user?token=123)
+------------------------------------------+
^ |
+-------+--------+3. GET /oauth-cli/finish +-------+------+
| OAuth 2.0 | Response: | OAuth 2.0 |
| Authz provider | welcome page | Client |
| ("Server") | +-----------------^+ ("Proxy") |
+-------+--------+ | 5. Respond with +-------+------+
^ | session token ^
| | |
+------+ | +------------------+
2. In browser: | | | 1. Get authz URL
Visit AuthURL | | | POST /oauth-cli/start
+--------+-------+-+
Response: | CLI Application | Response: AuthURL
redirect-to | ("Client"/"User")|
GET /oauth-cli/finish+---+----+---------+
?code=...&port=... | ^
| |
+----+
6. GET localhost:<port>/
With some query values
e.g. new_secret=123
Dependencies
~52MB
~1M SLoC