RiddleMan / doken

Tool for getting tokens from OAuth 2.0/OpenID Connect providers
MIT License
12 stars 0 forks source link
authentication chromium cli command-line jwt made-with-rust oauth2 oidc openid-connect rust terminal token tool

doken

Rust dependency status

Tool for getting tokens from OAuth 2.0/OpenID Connect providers.

Features

Prerequisites

Installation

Install pre-built binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/RiddleMan/doken/releases/latest/download/doken-installer.sh | sh

Install pre-built binaries via PowerShell script

Ensure you run this command in Adminstrative shell.

Set-ExecutionPolicy Bypass -Scope Process -Force; irm https://github.com/RiddleMan/doken/releases/latest/download/doken-installer.ps1 | iex

Install pre-built binaries via Homebrew

brew install RiddleMan/homebrew-tap/doken

Usage

Basic Authorization Code with PKCE grant

The most common use case that most of the Identity Providers support (if your IdP doesn't support PKCE, please use authorization-code grant).

It opens a browser to pass the grant and authorize. Returns an _accesstoken as an output.

doken \
  --token-url https://my-idp.com/oauth/token \
  --authorization-url https://my-idp.com/authorize \
  --callback-url https://my-app-domain.com/oauth2/callback \
  --client-id <client_id>

Providing arguments as environment variables

If you have an Identity Provider you constantly request, then you provide all of them using environment variables. Every argument could be passed as the following DOKEN_MY_ARGUMENT ex. DOKEN_TOKEN_URL.

export DOKEN_TOKEN_URL=https://my-idp.com/oauth/token 
export DOKEN_AUTHORIZATION_URL=https://my-idp.com/authorize
export DOKEN_CALLBACK_URL=https://my-app-domain.com/oauth2/callback
export DOKEN_CLIENT_ID=<client_id>
export DOKEN_SECRET_ID=<client_secret>
export DOKEN_GRANT=authorization-code

doken

Sharing project's IdP settings via .env file

The tool detects the closest .env file in a tree structure to make it easier to execute repeatable commands within the scope of the project. To do so create a .env file at the root of your project with the following contents:

DOKEN_TOKEN_URL=https://my-idp.com/oauth/token 
DOKEN_AUTHORIZATION_URL=https://my-idp.com/authorize
DOKEN_CALLBACK_URL=https://my-app-domain.com/oauth2/callback
DOKEN_CLIENT_ID=<client_id>
DOKEN_SECRET_ID=<client_secret>
DOKEN_GRANT=authorization-code

Then retrieving a token goes like this:

doken

Saving multiple IdP profiles in ~/.doken/config.toml file

The tool allows you to store multiple profiles in TOML file like so:

# File ~/.doken/config.toml

# Example of all possible values
[profile.first_profile]
client_id = "<client_id>"
client_secret = "<client_secret>"
audience = "https://my-app-domain.com/api"
scope = "email profile"
authorization_url = "https://my-idp.com/authorize"
token_url = "https://my-idp.com/oauth/token"
callback_url = "https://my-app-domain.com/oauth2/callback"
grant = "authorization-code-with-pkce"

# Example of partially filled profile
[profile.second_profile]
discovery_url = "https://my-idp.com/discovery"
callback_url = "https://my-app-domain.com/oauth2/callback"
grant = "authorization-code-with-pkce"

To authorize against first profile you type:

doken --profile first_profile

To use second profile with different client_id/client_secret pair you execute:

doken --profile second_profile --client-id <client_id> --client-secret-stdin

There's even option to overwrite some of settings defined in profile by providing an argument in command line:

doken --profile first_profile --client-id <different_client_id>

If some option is required, but wasn't provided the tool will error:

$ doken --profile second_profile

error: the following required arguments were not provided:
  --client-id <CLIENT_ID>

Usage: doken --client-id <CLIENT_ID> --profile <PROFILE> --grant <GRANT> --callback-url <CALLBACK_URL>

For more information, try '--help'.

Usage with cURL

The power of this tool is the best while used with any request tools like cURL. Here's an example:

curl -H "Authorization: Bearer $(doken)" https://my-api-url.com/users

Authorization Code with PKCE grant with secret

doken \
  --token-url https://my-idp.com/oauth/token \
  --authorization-url https://my-idp.com/authorize \
  --callback-url https://my-app-domain.com/oauth2/callback \
  --client-id <client_id> \
  --client-secret-stdin

Client credentials grant with discovery url

doken \
  --discovery-url https://my-idp.com/.well-known/openid-configuration \
  --callback-url https://my-app-domain.com/oauth2/callback \
  --client-id <client_id> \
  --client-secret-stdin \
  --grant client-credentials

Implicit grant

⚠️ Not recommended. Use Authorization Code with PKCE Grant instead. Read more: link.

doken \
  --token-url https://my-idp.com/oauth/token \
  --authorization-url https://my-idp.com/authorize \
  --callback-url https://my-app-domain.com/oauth2/callback \
  --client-id <client_id> \
  --client-secret-stdin \
  --grant implicit

Resource Owner Password Client credentials grant

⚠️ Not recommended. Use Authorization Code Grant with PKCE instead. Read more: link.

doken \
  --discovery-url https://my-idp.com/.well-known/openid-configuration \
  --client-id <client_id> \
  --client-secret-stdin \
  --username <my_username> \
  --password-stdin \
  --grant resource-owner-password-client-credentials

Arguments priority

Doken gathers arguments to the command from various sources. Here's the list of least prioritized to the most, meaning that the last one overwrites values of the previous ones.

  1. .env file
  2. Environment variables ex. _DOKEN_CLIENT_ID=_
  3. Profiles from ~/.doken/config.toml
  4. Command arguments ex. _--client-id _

Token refresh details

The command tries to open a browser as rarely as possible. To achieve that the state (~/.doken.json) and refresh logic has been implemented.

Running the command in any of the authorization grants could result in one of these situations:

  1. If no data about _clientid in ~/.doken.json, then open a browser get token, save it in the state and output to the user
  2. If _accesstoken is available in the state, and it's valid, then output to the user
  3. If _accesstoken is invalid and _refreshtoken exists and it's valid, then refresh token, save in the state and output to the user
  4. If _accesstoken and _refreshtoken are invalid, then remove state and use case no. 1

Frequently asked questions

Can't find a correct location of config.toml

Location varies between operating systems:

License

doken is under the terms of the MIT License.

See the LICENSE file for details.