Authentication
Authentication enable the typegate to identify the user making the request and share some contextual data (called later "context" or "claims"). This data can then be used by policies or injected into various fields. Authenticated requests must use the Authorization
header to provide a token in one of the following format.
Basic authentication
Basic authentication is the simplest way to authenticate requests. It is done by sending a base64 encoded string of your username and password in the authorization header. Recall that base64 encoding is not encryption and can be easily reversed, thus the traffic must be encrypted with SSL/TLS when using basic authentication as your password will otherwise be visible.
Components | Values |
---|---|
Secrets | BASIC_[username]=password |
Header | Authorization: Basic base64(username:password) |
Context | { username } |
JWT authentication
A more secure way to authenticate requests is to use JSON Web Tokens. The context of a user is signed with a secret key and the typegate will verify the signature to ensure the context has not been tampered with. The JWT is then sent in the authorization header.
The JWT is usually generated by an external identity provider (IdP) such as Keycloak or Auth0 and limited in time. The typegate will check that the exp
(expiration time) and nbf
(not before) are valid if they exist in the context. The logic of refreshing expired tokens is left to the user or the IdP client library being used.
The typegate supports the most frequently used algorithms for signing the JWT and can be imported as using "jwk", "raw", "pkcs8" or "spki" formats (see SubtleCrypto documentation). For instance, an asymmetric key pair can be generated with the following command:
const keys = await crypto.subtle.generateKey(
{ name: "ECDSA", namedCurve: "P-384" },
true,
["sign", "verify"],
);
const publicKey = await crypto.subtle.exportKey("jwk", keys.publicKey);
// save keys.privateKey for later use
console.log(JSON.stringify(publicKey));
// in typegraph: Auth.jwt("keycloak", "jwk", {"name": "ECDSA", "namedCurve": "P-384"})
Even though, asymmetric encryption is recommended, HMAC-SHA256 is so commonly used that an alias is provided for it.
Components | Values |
---|---|
Secrets | [authentication]_JWT=secret |
Header | Authorization: Bearer token |
Context | { your_own_content } |
Note that for the sake of the demo, the token has no expiration time. Tokens should always be shorted lived and refreshed frequently to reduce the risk of unexpected access.
OAuth2 authorization
OAuth2 allows a user to grant limited access to their resources on one site, to another site, without having to expose their credentials. It is commonly used when the typegate needed to access restricted information in third-parties such as Google or GitHub.
Most of the time, the OAuth2 is managed by your identity provider and relies on the JWT authentication as explained above. However the typegate provides a simple way to handle the OAuth2 flow without IdP or when the system should be lightweight.
Components | Values |
---|---|
Secrets | [authentication]_CLIENT_ID=client_id , [authentication]_CLIENT_SECRET=client_secret |
Header | Authorization: Bearer token |
Context | { content_from_your_idp } |
The OAuth2 authorization system requires you to have a redis instance configured for the typegate to store states. See configuration for more details.
Token flow
The typegate uses PKCE based authorization. The steps are the following:
- Redirect the user to `https://[typegate].metatype.cloud/[typegraph]/auth/[authentication] with the following search parameters:
client_id
: The client id of your application defined in the typegraphredirect_uri
: The redirect URI of your application defined in the typegraphstate
: A random string used to prevent CSRFcode_challenge
: A hashed of the string used as a code verifiercode_challenge_method
: Set to S256scope
: The scope of the token (optional)
- When the user has completed the flow, the typegate will redirect the user to
https://your-website.com/login
with an authorizationcode
that you can exchange for a token from the typegate as follows. It is done by making aPOST
request tohttps://[typegate].metatype.cloud/[typegraph]/auth/token
with the following body:
code
: The authorization code from the typegatecode_verifier
: The inital code verifiergrant_type
: Set toauthorization_code
client_id
: The previous client idredirect_uri
: The previous redirect URI
const claims = await fetch(
"https://[typegate].metatype.cloud/[typegraph]/auth/token",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
code: "code",
code_verifier: "code_verifier",
grant_type: "authorization_code",
client_id: "client_id",
redirect_uri: "redirect_uri",
}),
},
);
const { token } = await claims.json();
The returned token will have the following fields:
access_token
: Used to make authentified requestsrefresh_token
: Used to get another tokentoken_type
: Set to Bearerexpires_in
: Expiration timescope
: The scope of the token
- The
access_token
can then be used as JWT in theAuthorization
header of your requests to make authentified calls.
- When the token is expired, you can claim another token by using your
refresh_token
by making aPOST
request to the token endpoint [https://[typegate].metatype.cloud/[typegraph]/auth/token] with the following body:
grant_type
: Set torefresh_token
refresh_token
: The previously received refresh tokenscope
: The new token scope (optional)
const claims = await fetch(
"https://[typegate].metatype.cloud/[typegraph]/auth/token",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "refresh_token",
refresh_token: "refresh_token",
}),
},
);
const { token } = await claims.json();
OpenID Connect
OpenID Connect is an authentication layer on top of OAuth2. It is used to verify the identity of the user and retrieve basic information about them. You can add openid
to the OAuth2 scope and you will receive an id_token
in the response. The id_token
is a JWT that contains the user's information and is signed by the IdP.
Embedded providers
Frequent OAuth2 providers are embedded and can be directly used in the typegraph.
from typegraph.graph.params import Auth
Auth.oauth2(
provider="github",
scopes=["openid", "profile", "email"],
clients=[
{
"id_secret": "APP_CLIENT_ID",
"redirect_uri_secret": "APP_REDIRECT_URI",
}
],
)
The available providers are:
digitalocean
discord
dropbox
facebook
github
gitlab
google
instagram
linkedin
microsoft
reddit
slack
stackexchange
twitter