oidc
Generated by tinox doc
tinox.core.oidc, split out of the bundled stdlib as a standalone tinox-central package.
| Module | Version | Group |
|---|---|---|
crypto (no local docs) | 1.1.7 | tinox.core |
http_server (no local docs) | 1.2.9 | tinox.core |
json (no local docs) | 1.1.8 | tinox.core |
jwt (no local docs) | 1.1.8 | tinox.core |
oauth2 (no local docs) | 1.1.8 | tinox.core |
Verify id token
import tinox.core.oidc
class Main
{
fnc main() -> Int32
{
const 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"
)
const req: OAuth2AuthorizeRequest = client.buildAuthorizeUrl("openid email")
println("redirect user to: " + req.url)
// Callback handler, after the provider redirects back with ?code=...
const 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
{
const 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"
)
const webApp: OidcWebApp = OidcWebApp::new(client, "a-long-random-cookie-sealing-secret")
const server: HttpServer = HttpServer::new(8080)
webApp.install(server) // registers /login and /callback
server.get("/", ctx => {
if (!webApp.requireLogin(ctx))
{
return // already redirected to /login
}
const user: Map<String, JsonValue> = webApp.currentUser(ctx)
ctx.response.text("Welcome, " + user["email"].getString())
})
server.listen()
return 0
}
}
class OidcClient
Fields
issuer | String | |
jwksUri | String | |
clientId | String | |
oauth | OAuth2Client |
Methods
fn new(issuer: String, authorizeUrl: String, tokenUrl: String, jwksUri: String, clientId: String, clientSecret: String, redirectUri: String) → OidcClient
@Throwsfn buildAuthorizeUrl(scope: String) → OAuth2AuthorizeRequest
@Throwsfn exchangeCode(code: String, codeVerifier: String) → OidcTokenResponse
@Throwsfn refresh(refreshToken: String) → OidcTokenResponse
@Throwsfn verifyAndWrap(tr: OAuth2TokenResponse) → OidcTokenResponse
@Throwsfn verifyIdToken(idToken: String) → Map<String, JsonValue>
@Errorclass OidcError
* Invalid OIDC configuration, token or session.
Fields
message | String |
class OidcTokenResponse
Fields
accessToken | String | |
refreshToken | String | |
tokenType | String | |
expiresIn | Int64 | |
idToken | String | |
claims | Map<String, JsonValue> | |
ok | Bool | |
errorMessage | String |
class OidcWebApp
Fields
client | OidcClient | |
cookieSecret | String | |
loginPath | String | |
callbackPath | String | |
sessionCookieName | String | |
pendingCookieName | String |
Methods
@Throwsfn new(client: OidcClient, cookieSecret: String) → OidcWebApp
@Throwsfn install(server: HttpServer) → Nothing
@Throwsfn installWithSessions(server: HttpServer, sessions: SessionManager) → Nothing
fn requireSession(ctx: HttpContext, sessions: SessionManager) → Bool
fn logoutSession(ctx: HttpContext, sessions: SessionManager) → Nothing
@Throwsfn 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
class Session
Fields
valid | Bool | |
reason | String | |
id | String | |
claims | Map<String, JsonValue> | |
issuedAt | Int64 | |
expiresAt | Int64 | |
seenAt | Int64 | |
renewed | Bool |
Methods
fnc invalid(reason: String) → Session
class SessionManager
Fields
secrets | List<String> | |
cookieName | String | |
cookiePath | String | |
cookieDomain | String | |
cookieSecure | Bool | |
cookieSameSite | String | |
lifetimeSec | Int64 | |
idleSec | Int64 | |
renewAfterSec | Int64 | |
maxRevoked | Int64 | |
epochMs | Int64 | |
revoked | Map<String, Int64> | |
dropped | Int64 | |
lock | Mutex |
Methods
@Throwsfn create(secrets: List<String>) → SessionManager
fn name(cookieName: String) → SessionManager
fn path(path: String) → SessionManager
fn domain(domain: String) → SessionManager
fn secure(enabled: Bool) → SessionManager
fn sameSite(value: String) → SessionManager
@Throwsfn lifetime(seconds: Int64) → SessionManager
@Throwsfn idle(seconds: Int64) → SessionManager
@Throwsfn renewAfter(seconds: Int64) → SessionManager
@Throwsfn maxRevocations(count: Int64) → SessionManager
@Throwsfn start(ctx: HttpContext, claims: Map<String, JsonValue>) → Session
@Throwsfn load(ctx: HttpContext) → Session
@Throwsfn touch(ctx: HttpContext) → Session
@Throwsfn rotate(ctx: HttpContext) → Session
@Throwsfn end(ctx: HttpContext) → Nothing
fn endAll() → Nothing
fn revocationsDropped() → Int64
@Throwsfn inspect(ctx: HttpContext, renew: Bool) → Session
fn isRevoked(id: String, issuedAt: Int64) → Bool
fn revoke(id: String, expiresAt: Int64) → Nothing
@Throwsfn issue(ctx: HttpContext, s: Session) → Nothing
fnc newId() → String
fnc readCookie(ctx: HttpContext, name: String) → String