oidc

Generated by tinox doc

tinox.core.oidc, split out of the bundled stdlib as a standalone tinox-central package.

ModuleVersionGroup
crypto1.0.1tinox.core
http_server1.0.1tinox.core
json1.0.0tinox.core
jwt1.0.1tinox.core
oauth21.0.1tinox.core

Verify id token

import tinox.core.oidc;

class Main
{
    fnc main() -> Int32
    {
        let client: OidcClient = OidcClient::new(
            "https://accounts.google.com",
            "https://accounts.google.com/o/oauth2/v2/auth",
            "https://oauth2.googleapis.com/token",
            "https://www.googleapis.com/oauth2/v3/certs",
            "my-client-id",
            "my-client-secret",
            "https://myapp.example.com/callback"
        );

        let req: OAuth2AuthorizeRequest = client.buildAuthorizeUrl("openid email");
        println("redirect user to: " + req.url);

        // Callback handler, after the provider redirects back with ?code=...
        let tokens: OidcTokenResponse = client.exchangeCode("the-code-from-callback", req.codeVerifier);
        if tokens.ok
        {
            // id_token signature + iss/aud/exp/nbf already verified here
            println("subject: " + tokens.claims["sub"].getString());
        }
        else
        {
            println("login failed: " + tokens.errorMessage);
        }
        return 0;
    }
}

Turnkey web login

import tinox.core.oidc;
import tinox.core.http_server;

class Main
{
    fnc main() -> Int32
    {
        let client: OidcClient = OidcClient::new(
            "https://accounts.google.com",
            "https://accounts.google.com/o/oauth2/v2/auth",
            "https://oauth2.googleapis.com/token",
            "https://www.googleapis.com/oauth2/v3/certs",
            "my-client-id",
            "my-client-secret",
            "https://myapp.example.com/callback"
        );
        let webApp: OidcWebApp = OidcWebApp::new(client, "a-long-random-cookie-sealing-secret");

        let server: HttpServer = HttpServer::new(8080);
        webApp.install(server); // registers /login and /callback

        server.get("/", ctx => {
            if !webApp.requireLogin(ctx)
            {
                return; // already redirected to /login
            }
            let user: Map<String, JsonValue> = webApp.currentUser(ctx);
            ctx.response.text("Welcome, " + user["email"].getString());
        });

        server.listen();
        return 0;
    }
}

class OidcClient

Fields

issuerString
jwksUriString
clientIdString
oauthOAuth2Client

Methods

fn new(issuer: String, authorizeUrl: String, tokenUrl: String, jwksUri: String, clientId: String, clientSecret: String, redirectUri: String) → OidcClient
fn buildAuthorizeUrl(scope: String) → OAuth2AuthorizeRequest
fn exchangeCode(code: String, codeVerifier: String) → OidcTokenResponse
fn refresh(refreshToken: String) → OidcTokenResponse
fn verifyAndWrap(tr: OAuth2TokenResponse) → OidcTokenResponse
fn verifyIdToken(idToken: String) → Map<String, JsonValue>

class OidcTokenResponse

Fields

accessTokenString
refreshTokenString
tokenTypeString
expiresInInt64
idTokenString
claimsMap<String, JsonValue>
okBool
errorMessageString

class OidcWebApp

Fields

clientOidcClient
cookieSecretString
loginPathString
callbackPathString
sessionCookieNameString
pendingCookieNameString

Methods

fn new(client: OidcClient, cookieSecret: String) → OidcWebApp
fn install(server: HttpServer) → Nothing
fn requireLogin(ctx: HttpContext) → Bool
fn currentUser(ctx: HttpContext) → Map<String, JsonValue>
fn logout(ctx: HttpContext) → Nothing
fnc sealJson(data: Map<String, JsonValue>, secret: String) → String
fnc unsealJson(sealed: String, secret: String) → Map<String, JsonValue>
fnc readCookie(ctx: HttpContext, name: String) → String