Takagi enables you to use GitHub as an OpenID Connect (OIDC) provider. With it, you can use GitHub to identify your application's users without needing to implement specific support for GitHub's OAuth2 API.
Takagi is a sister project to Snowflake, which does the same thing but for Discord. You should check that out, too.
Important
Takagi requires HTTPS for external connections. (By default, HTTP connections on localhost are fine; see
Configuration.)
Docker is the only supported way of running Takagi. You will almost always
want to set the TAKAGI_ALLOWED_HOSTS environment variable; see Configuration.
Note
Throughout this README, takagi.example.com will be used as a placeholder for the domain at which your
Takagi instace is reachable.
After installing Takagi, I recommend taking a look at the interactive API documentation at
https://takagi.example.com/docs.
Supported tags
| Name | Description | Example |
|---|---|---|
latest |
The latest stable version of Takagi. | ghcr.io/celsiusnarhwal/takagi:latest |
| Major version number | The latest release of this major version of Takagi. May be optionally prefixed with a v. |
ghcr.io/celsiusnarhwal/takagi:1ghcr.io/celsiusnarhwal/takagi:v1 |
| Minor version number | The latest release of this minor version of Takagi. May be optionally prefixed with a v. |
ghcr.io/celsiusnarhwal/takagi:1.0ghcr.io/celsiusnarhwal/takagi:v1.0 |
| Exact version number | This version of Takagi exactly. May be optionally prefixed with a v. |
ghcr.io/celsiusnarhwal/takagi:1.0.0ghcr.io/celsiusnarhwal/takagi:v1.0.0 |
edge |
The latest commit to Takagi's main branch. Unstable. |
ghcr.io/celsiusnarhwal/takagi:edge |
services:
takagi:
image: ghcr.io/celsiusnarhwal/takagi:latest
container_name: takagi
restart: unless-stopped
ports:
- "8000:8000"
environment:
- TAKAGI_ALLOWED_HOSTS=takagi.example.com
volumes:
- /some/directory/on/your/machine:/app/takagi/datadocker run --name takagi \
--restart unless-stopped \
-p "8000:8000" \
-e "TAKAGI_ALLOWED_HOSTS=takagi.example.com"
-v "/some/directory/on/your/machine:/app/takagi/data" \
ghcr.io/celsiusnarhwal/takagi:latestFirst, create an OAuth application in your GitHub developer settings. Put in whatever you want for the application name and homepage URL.
For the authorization callback URL, you must set it to https://takagi.example.com/r/{YOUR_REDIRECT_URI},
where {YOUR_REDIRECT_URI} is the actual intended redirect URI for your application. For example, a redirect
URI of https://myapp.example.com/callback would be set as as
https://takagi.example.com/r/https://myapp.example.com/callback.
Tip
If you're unable to control the redirect URI your OIDC client provides to Takagi, set
the TAKAGI_FIX_REDIRECT_URIS environment variable to true. See Configuration
for details.
From there, Takagi works just like any other OIDC provider. Your app redirects to Takagi for authorization;
upon succcessful authorization, Takagi provides your app with an authorization code, which your app returns
to Takagi in exchange for an access token and an ID token. The access token can be sent to Takagi's
/userinfo endpoint to obtain the associated identity claims, or your application can decode the ID token
directly to obtain the same claims.
Frankly, if you're reading this then you should already know how this works.
| Endpoint | Path |
|---|---|
| Authorization | /authorize |
| Token | /token |
| User Info | /userinfo |
| Introspection | /introspect |
| Revocation | /revoke |
| Deauthorization | /deauthorize |
| JSON Web Key Set | /.well-known/jwks.json |
| OIDC Discovery | /.well-known/openid-configuration |
| WebFinger | /.well-known/webfinger |
| Scope | Requests | Required? |
|---|---|---|
openid |
To authenticate using OpenID Connect. | Yes |
profile |
Basic information about the user's GitHub account. | No |
email |
The primary email address associated with the user's GitHub account.1 | No |
groups |
A list of IDs of organizations the user is a member of and has authorized your application to access. | No |
Important
By default, tokens issued by Takagi do not expire.2 This mirrors the behavior of GitHub OAuth2 access tokens, which
also do not expire. If you would like Takagi-issued tokens to expire, set the TAKAGI_TOKEN_LIFETIME
environment variable (see Configuration).
Depending on the provided scopes, Takagi-issued ID tokens include some subset of the following claims:
| Claim | Description | Required Scopes (in addition to openid) |
|---|---|---|
iss |
The URL at which the client accessed Takagi. | None |
sub |
The ID of the user's GitHub account. | None |
aud |
The client ID of your GitHub application. | None |
iat |
The Unix time at which the token was issued. | None |
exp |
The Unix time past which the token should be considered expired and thus no longer valid. | None |
preferred_username |
The username of the user's GitHub account. | profile |
name |
The display name of the user's GitHub account. | profile |
nickname |
Same as name. |
profile |
picture |
The URL of the avatar of the user's GitHub account. | profile |
profile |
The URL of the user's GitHub profile. | profile |
updated_at |
The Unix time at which the user's profile information was last updated. | profile |
email |
The primary email address associated with the user's GitHub account.1 | email |
email_verified |
Whether the primary email address assocaited with the user's GitHub account is verified. | email |
groups |
A list of IDs of organizations the user is a member of and has authorized your application to access. Each organization ID is prefixed with org:. If the user does not authorize your application to access any organizations, this claim will not be present. |
groups |
nonce |
If the nonce parameter was sent to the authorization endpoint, this claim will contain its value. |
None |
Takagi-issued access tokens include the following claims:
| Claim | Description | Required Scopes (in addition to openid) |
|---|---|---|
iss |
The URL at which the client accessed Takagi. | None |
sub |
The ID of the user's GitHub account. | None |
aud |
Same as iss. |
None |
iat |
The Unix time at which the token was issued. | None |
exp |
The Unix time past which the token should be considered expired and thus no longer valid. | None |
token |
The OAuth2 access token granted by GitHub. This token is encrypted and only usable by Takagi. | None |
The /userinfo endpoint returns the same claims as ID tokens but does not include iss, aud,
iat, exp, or nonce.
Takagi provides a WebFinger endpoint at /.well-known/webfinger
to enable the discovery of Takagi as the OIDC provider for email addresses at domains permitted by the
TAKAGI_ALLOWED_WEBFINGER_HOSTS environment variable (see Configuration). The endpoint
only supports acct: URIs containing email addresses and does not support any link relations other than OpenID Connnect.
The endpoint will return an HTTP 404 error for email addresses at non-whitelisted domains.
As previously mentioned, Takagi requires HTTPS for external connections. If you're serving Takagi behind a reverse proxy and connecting to the reverse proxy over HTTPS, you will likely need to configure Uvicorn — which Takagi uses under the hood — to trust the IP address of your reverse proxy.
You can do this by setting the UVICORN_FORWARDED_ALLOW_IPS environment variable to a comma-separated list of IP
addresses or networks, at least one of which must match the IP of your reverse proxy. You can also set it to * to
trust all IP addresses, but this is generally not recommended.
For more information, see Uvicorn's documentation.
Note
This is an advanced feature most users won't need.
By default, Takagi writes its private keys to /app/takagi/data, which you are instructed to mount on your host machine
(see Installation). As an alternative to this, Takagi allows you to provide keys externally.
First, you'll need to generate a suitable private key3 using the following command:4
docker exec takagi keygenOr, if you don't have a running Takagi instance:
docker run ghcr.io/celsiusnarhwal/takagi keygenSecond, you'll need to provide the key to Takagi in one of two ways:
- As the value of the
TAKAGI_KEYSETenvironment variable. This may be useful in serverless enviroments where mounting/app/takagiisn't possible. - As a file mounted into Takagi's container whose path is provided via
TAKAGI_KEYSET. This file cannot be located within/app/takagi. This allows for compatibility with Docker secrets.
Warning
Switching from Takagi-managed private keys to custom private keys (or vice versa) will invalidate any active Takagi-issued tokens and cause any in-process authorizations to fail.
For reference, a suitable private keyset looks like this (click to expand):
// For demonstration purposes only, do not actually use this keyset. Obviously.
{
"keys": [
{
"n": "1PZYs3MrRkF83qVCoZ1qEJ3doCWaOflTVaZNceqYx4F1m_p_prUlzpBlsIky0q45e4ov3hehSh3FkvlnXLzYrD_Ewgwjy7xwIEhR7zyUUYMlUSCdb0Bq8mFRVG0zPYOSAY3CFkadnH0vwroJJcnc_mmAssfu6eUaIB7kfnqFx2RI3jXzi-runGrki8Y2yVAjovlgulX04Y0GD60kt1-vwva8Goci8Rij0IIna4GyKjYwxzKrOvMqI9_td7JJItF4QiDMd_SSjf8p6TenaWG26gb0vWhkzR6zWs-lVxMJYFkhnrGRk9urq6Zk4r_mmez7NPIyYAS5GWUW_Of7c-_h6w",
"e": "AQAB",
"d": "DK-gGRCDQ2wjRCAUGAyIhPTifue-iDWSAUgm1OJkt32-w8voTsX7upJffGSv4lz-j51rvI8rzH55hofU4HFfduNVlTmj6D8RbtrgBqBVNYXaczq-JiJwPIAPmDfpFYEA8ZbAORN70BalAbSTVuzvfThLslq2oLhFFiTA98fUsEvtN0O_FwNgvzJGfwvVGEmP6grYjqQr0NSqpD3tj2fq2AC5531ri1fjPyDE9wvQM4_EkZ0eOHtJW7ztfimiv_pgz1B_V6p26_FMhzhKkBepyMIewGPY4mzP-v4zlQILL6uYP9IbOZf1bCGjgcPF5lxQkL9Hjq1z0bRrpQgkoowAAQ",
"p": "79NHLDfiFlo-lml4yVRVrRbrFZknbO506NdB-JKNcs1H7uYf_UTiY0E-oScvTZdgti0lxWh8syUCmXhkqLykrGgHG1M7uSmGACki35_diG5VTyIJuO4g92lLjw6d0slBcqaLZyeWctC_gU8F262HX97BombfIM6Nb2pWQ7zAQ-s",
"q": "41NDWHVyTZkOjgwd8WIuYmBVd59MRYXyo_sBFkku8WyH21q-B7iTuMFcb7i61e0Qv8HPAchljqqEl3d91DpMOFTEy-MHoV2jn7_D4Grxsqb6mNomdOcC0oN4o7ZAvdJzffVfJXWBFwNbXyg7o3Byyr4Rl3OSi8HonYKVR80tWgE",
"dp": "7SK6Q2zWb0e4jz2nI1vyg34f4XFY3ItEql7-am1u089Li1uc0e_k8kO3S93VFiHSjRBDQtk4RGMaGOpEjdxJ7_fE3y4D5ei7CTmjs_79LEP8soxzlJpRmpJRFhlb0OsTfexT9yHbz5e9ZHzgzADf1NoMGSsjAet7SmmY9s2SRxU",
"dq": "2XJO7DHD-agbvRKoHbqdxeqCNp_BFIuxctvpyUiNx8_aEKA3QCl13HfRlOiuh21x5QtdmUX4p0RC-qQJT9XIDOZBLQpoxRlOJ8QGeQezVQHWmhmqSY6kK3wpDOiL-0dwxB7POYSxy7KhV1-j1I3-sCKpryaVGmyMtwYvB3SjGgE",
"qi": "gYDgAbG3OHiQzLF76WuVfOoS2yUc_wJEExTvAYaRZ-yPEQBk4b3J5rYZUmxGJUMVzrNBEfMKR0bXwFB76JR53jD_NEOBUseTd4E4YldX_CMrw2XaopE4ftuR-5EklaOP2jP6Zqr3QQpqKpO9G-nC8ZQY5Gz4DWEtz4v0gUvvV_I",
"use": "sig",
"alg": "RS256",
"kty": "RSA",
"kid": "D-byh_ZgjoJOOho7vui-P_7WENzRKxgUAgiHZJOcHig"
},
{
"k": "9AY2hzl0Sje9Zwv_XNHuz1BdEESmkVplMvap4KGfIeI",
"use": "enc",
"alg": "A256GCM",
"kty": "oct",
"kid": "GtMvEe77qYhPK6sOkWjuU9Yynzv-u8WYLCdwXN-qkGA"
}
]
}If TAKAGI_KEYSET is set, there's no need to mount /app/takagi/data. On startup, Takagi
will log a message affirming that a custom private keyset is in use.
If you think Takagi's private keys have been compromised, you can rotate them with the following command:4
docker exec takagi rotateThis only has any effect if Takagi is managing its own keys. If you're using custom private keys, you'll have to change them manually.
Warning
Doing this will invalidate any active Takagi-issued tokens and cause any in-process authorizations to fail.
Takagi is configurable through the following environment variables (all optional):
| Environment Variable | Type | Description | Default |
|---|---|---|---|
TAKAGI_ALLOWED_HOSTS |
String | A comma-separated list of hostnames at which Takagi may be accessed. Wildcard domains (e.g., *.example.com) and IP addresses are supported. You can also set this to * to allow all hostnames, but this is not recommended.Loopback addresses (e.g., localhost) are always included. |
localhost,127.0.0.1,::1 |
TAKAGI_ALLOWED_CLIENTS |
String | A comma-separated list of GitHub application client IDs. Takagi will only fulfill authorization requests for client IDs in this list. This can be set to * to allow all client IDs. |
* |
TAKAGI_BASE_PATH |
String | The URL path at which Takagi is being served. This may be useful if you're serving Takagi behind a reverse proxy. | / |
TAKAGI_FIX_REDIRECT_URIS |
Boolean | Whether to automatically correct redirect URIs to subpaths of Takagi's /r endpoint as necessary. This may be useful for OIDC clients that don't allow you to set the redirect URI they use.The redirect URI you set in your GitHub application's settings must always be a subpath of /r regardless of this setting. |
false |
TAKAGI_TOKEN_LIFETIME |
String | A Go duration string representing the amount of time after which Takagi-issued tokens should expire. In addition to the standard Go units, you can use d for day, w for week, mm for month, and y for year.5If provided, it must be greater than or equal to 60 seconds. If not provided, Takagi-issued tokens will never expire.2 |
N/A |
TAKAGI_ROOT_REDIRECT |
String | Where Takagi's root path redirects to. Must be repo, settings, docs, or off.repo redirects to Takagi's GitHub repository; settings redirects to the user's GitHub account settings; docs redirects to Takagi's interactive API documentation; off responds with an HTTP 404 error.Setting this to docs will force TAKAGI_ENABLE_DOCS to be true. |
repo |
TAKAGI_TREAT_LOOPBACK_AS_SECURE |
Boolean | Whether Takagi will consider loopback addresses (e.g., localhost) to be secure even if they don't use HTTPS. |
true |
TAKAGI_RETURN_TO_REFERRER |
Boolean | If this is true and the user denies an authorization request, Takagi will redirect the user back to the initiating URL.6 Otherwise, Takagi behaves according to OpenID Connect Core 1.0 § 3.1.2.6. |
false |
TAKAGI_ALLOWED_WEBFINGER_HOSTS |
String | A comma-separated lists of domains allowed in acct: URIs sent to Takagi's WebFinger endpoint. The endpoint will return an HTTP 404 error for URIs with domains not permitted by this setting.Wildcard domains (e.g., *.example.com) are supported, but the unqualified wildcard (*) is not. |
N/A |
TAKAGI_KEYSET |
String | A private keyset or a path to a file containing one. See Custom Private Keys. | N/A |
TAKAGI_ENABLE_DOCS |
Boolean | Whether to serve Takagi's interactive API documentation at /docs. This also controls whether Takagi's OpenAPI schema is served at /openapi.json.This is forced to be true if TAKAGI_ROOT_REDIRECT is set to docs. |
true |
Uvicorn will respect most7 of its own environment variables if they are set, but UVICORN_FORWARDED_ALLOW_IPS is the only one supported by Takagi. Please don't open an issue if you set any of the others and something breaks.
Footnotes
-
This is the email address at which the user recieves account-related notifications from GitHub. It is not necessarily the same as the email address publicly visible on the user's GitHub profile. ↩ ↩2
-
Technically, they expire on December 31st, 9999 at 23:23:59.999999 UTC, but you will die long before then so don't worry about it. ↩ ↩2
-
It's possible to create a key yourself, but there are several requirements. I recommend you use
takagi keygeninstead. ↩ -
Assuming Takagi's container is named
takagi. Docker Compose users can also usedocker compose exec. ↩ ↩2 -
1 day = 24 hours, 1 week = 7 days, 1 month = 30 days, and 1 year = 365 days. ↩
-
Specifically, if the
Refererheader was sent to the authorization endpoint and the callback endpoint recieves anerrorparameter with a value ofaccess_denied, Takagi will redirect to the URL that was given byRefererat the authorization endpoint. ↩ -
With the exceptions of
UVICORN_HOSTandUVICORN_PORT. ↩