Packages

Shared types for use with the Stytch Authentication API. Magic Link and Passcode auth supported. For use with stytch_client package.

Current section

Files

Jump to
stytch_codecs src stytch_codecs.gleam
Raw

src/stytch_codecs.gleam

import gleam/dynamic/decode
import gleam/json
/// Error messages received from the stytch service
pub type StytchClientError {
StytchClientError(
status_code: Int,
request_id: String,
error_type: String,
error_message: String,
error_url: String,
)
}
pub fn stytch_client_error_to_json(
stytch_client_error: StytchClientError,
) -> json.Json {
let StytchClientError(
status_code:,
request_id:,
error_type:,
error_message:,
error_url:,
) = stytch_client_error
json.object([
#("status_code", json.int(status_code)),
#("request_id", json.string(request_id)),
#("error_type", json.string(error_type)),
#("error_message", json.string(error_message)),
#("error_url", json.string(error_url)),
])
}
pub fn stytch_client_error_decoder() -> decode.Decoder(StytchClientError) {
use status_code <- decode.field("status_code", decode.int)
use request_id <- decode.field("request_id", decode.string)
use error_type <- decode.field("error_type", decode.string)
use error_message <- decode.field("error_message", decode.string)
use error_url <- decode.field("error_url", decode.string)
decode.success(StytchClientError(
status_code:,
request_id:,
error_type:,
error_message:,
error_url:,
))
}
// ============================================================================
/// Request to create a magic link.
/// When stytch receives this request, it will send an e-mail, authenticate the user
/// in the clicked link, and redirect back to somewhere in your service.
pub type MagicLinkLoginOrCreateRequest {
MagicLinkLoginOrCreateRequest(email: String)
}
pub fn magic_link_login_or_create_request_to_json(
magic_link_login_or_create_request: MagicLinkLoginOrCreateRequest,
) -> json.Json {
let MagicLinkLoginOrCreateRequest(email:) = magic_link_login_or_create_request
json.object([
#("email", json.string(email)),
])
}
pub fn magic_link_login_or_create_request_decoder() -> decode.Decoder(
MagicLinkLoginOrCreateRequest,
) {
use email <- decode.field("email", decode.string)
decode.success(MagicLinkLoginOrCreateRequest(email:))
}
// ============================================================================
/// Request to log in with a passcode.
/// When stytch receives this it will send a passcode to the user's e-mail address.
/// It is up to you to process the passcode and authenticate it with stytch.
pub type PasscodeLoginOrCreateRequest {
PasscodeLoginOrCreateRequest(email: String)
}
pub fn passcode_login_or_create_request_to_json(
passcode_login_or_create_request: PasscodeLoginOrCreateRequest,
) -> json.Json {
let PasscodeLoginOrCreateRequest(email:) = passcode_login_or_create_request
json.object([
#("email", json.string(email)),
])
}
pub fn passcode_login_or_create_request_decoder() -> decode.Decoder(
PasscodeLoginOrCreateRequest,
) {
use email <- decode.field("email", decode.string)
decode.success(PasscodeLoginOrCreateRequest(email:))
}
// ============================================================================
/// Response to a request to create or log into an account.
///
/// Used by both magic links and OTP login_or_create
pub type LoginOrCreateResponse {
LoginOrCreateResponse(
status_code: Int,
request_id: String,
user_id: String,
email_id: String,
)
}
pub fn login_or_create_response_to_json(
magic_link_login_or_create_response: LoginOrCreateResponse,
) -> json.Json {
let LoginOrCreateResponse(status_code:, request_id:, user_id:, email_id:) =
magic_link_login_or_create_response
json.object([
#("status_code", json.int(status_code)),
#("request_id", json.string(request_id)),
#("user_id", json.string(user_id)),
#("email_id", json.string(email_id)),
])
}
pub fn login_or_create_response_decoder() -> decode.Decoder(
LoginOrCreateResponse,
) {
use status_code <- decode.field("status_code", decode.int)
use request_id <- decode.field("request_id", decode.string)
use user_id <- decode.field("user_id", decode.string)
use email_id <- decode.field("email_id", decode.string)
decode.success(LoginOrCreateResponse(
status_code:,
request_id:,
user_id:,
email_id:,
))
}
// ============================================================================
/// Request to authenticate a stytch token returned from login.
pub type TokenAuthenticateRequest {
TokenAuthenticateRequest(token: String, session_duration_minutes: Int)
}
pub fn token_authenticate_request_to_json(
token_authenticate_request: TokenAuthenticateRequest,
) -> json.Json {
let TokenAuthenticateRequest(token:, session_duration_minutes:) =
token_authenticate_request
json.object([
#("token", json.string(token)),
#("session_duration_minutes", json.int(session_duration_minutes)),
])
}
pub fn token_authenticate_request_decoder() -> decode.Decoder(
TokenAuthenticateRequest,
) {
use token <- decode.field("token", decode.string)
use session_duration_minutes <- decode.field(
"session_duration_minutes",
decode.int,
)
decode.success(TokenAuthenticateRequest(token:, session_duration_minutes:))
}
// ============================================================================
pub type PasscodeAuthenticateRequest {
PasscodeAuthenticateRequest(
code: String,
method_id: String,
session_duration_minutes: Int,
)
}
pub fn passcode_authenticate_request_to_json(
passcode_authenticate_request: PasscodeAuthenticateRequest,
) -> json.Json {
let PasscodeAuthenticateRequest(code:, method_id:, session_duration_minutes:) =
passcode_authenticate_request
json.object([
#("code", json.string(code)),
#("method_id", json.string(method_id)),
#("session_duration_minutes", json.int(session_duration_minutes)),
])
}
pub fn passcode_authenticate_request_decoder() -> decode.Decoder(
PasscodeAuthenticateRequest,
) {
use code <- decode.field("code", decode.string)
use method_id <- decode.field("method_id", decode.string)
use session_duration_minutes <- decode.field(
"session_duration_minutes",
decode.int,
)
decode.success(PasscodeAuthenticateRequest(
code:,
method_id:,
session_duration_minutes:,
))
}
// ============================================================================
pub type SessionTokenAuthenticateRequest {
SessionTokenAuthenticateRequest(
session_token: String,
session_duration_minutes: Int,
)
}
pub fn session_token_authenticate_request_to_json(
session_token_authenticate_request: SessionTokenAuthenticateRequest,
) -> json.Json {
let SessionTokenAuthenticateRequest(session_token:, session_duration_minutes:) =
session_token_authenticate_request
json.object([
#("session_token", json.string(session_token)),
#("session_duration_minutes", json.int(session_duration_minutes)),
])
}
pub fn session_token_authenticate_request_decoder() -> decode.Decoder(
SessionTokenAuthenticateRequest,
) {
use session_token <- decode.field("session_token", decode.string)
use session_duration_minutes <- decode.field(
"session_duration_minutes",
decode.int,
)
decode.success(SessionTokenAuthenticateRequest(
session_token:,
session_duration_minutes:,
))
}
// ============================================================================
/// Response from Stytch when attempting to autenticate with any method.
pub type AuthenticateResponse {
AuthenticateResponse(
status_code: Int,
request_id: String,
user_id: String,
method_id: String,
session_token: String,
session_jwt: String,
)
}
pub fn authenticate_response_to_json(
magic_link_authenticate_response: AuthenticateResponse,
) -> json.Json {
let AuthenticateResponse(
status_code:,
request_id:,
user_id:,
method_id:,
session_token:,
session_jwt:,
) = magic_link_authenticate_response
json.object([
#("status_code", json.int(status_code)),
#("request_id", json.string(request_id)),
#("user_id", json.string(user_id)),
#("method_id", json.string(method_id)),
#("session_token", json.string(session_token)),
#("session_jwt", json.string(session_jwt)),
])
}
pub fn authenticate_response_decoder() -> decode.Decoder(AuthenticateResponse) {
use status_code <- decode.field("status_code", decode.int)
use request_id <- decode.field("request_id", decode.string)
use user_id <- decode.field("user_id", decode.string)
use method_id <- decode.field("method_id", decode.string)
use session_token <- decode.field("session_token", decode.string)
use session_jwt <- decode.field("session_jwt", decode.string)
decode.success(AuthenticateResponse(
status_code:,
request_id:,
user_id:,
method_id:,
session_token:,
session_jwt:,
))
}
// ============================================================================
pub type SessionAuthenticateResponse {
SessionAuthenticateResponse(
status_code: Int,
request_id: String,
user: StytchUser,
session_token: String,
session_jwt: String,
)
}
pub fn session_authenticate_response_to_json(
session_authenticate_response: SessionAuthenticateResponse,
) -> json.Json {
let SessionAuthenticateResponse(
status_code:,
request_id:,
user:,
session_token:,
session_jwt:,
) = session_authenticate_response
json.object([
#("status_code", json.int(status_code)),
#("request_id", json.string(request_id)),
#("user", stytch_user_to_json(user)),
#("session_token", json.string(session_token)),
#("session_jwt", json.string(session_jwt)),
])
}
pub fn session_authenticate_response_decoder() -> decode.Decoder(
SessionAuthenticateResponse,
) {
use status_code <- decode.field("status_code", decode.int)
use request_id <- decode.field("request_id", decode.string)
use user <- decode.field("user", stytch_user_decoder())
use session_token <- decode.field("session_token", decode.string)
use session_jwt <- decode.field("session_jwt", decode.string)
decode.success(SessionAuthenticateResponse(
status_code:,
request_id:,
user:,
session_token:,
session_jwt:,
))
}
// ============================================================================
/// Request to revoke a session.
///
/// Use for signout.
pub type SessionRevokeRequest {
SessionRevokeRequest(session_token: String)
}
pub fn session_revoke_request_to_json(
session_revoke_request: SessionRevokeRequest,
) -> json.Json {
let SessionRevokeRequest(session_token:) = session_revoke_request
json.object([
#("session_token", json.string(session_token)),
])
}
pub fn session_revoke_request_decoder() -> decode.Decoder(SessionRevokeRequest) {
use session_token <- decode.field("session_token", decode.string)
decode.success(SessionRevokeRequest(session_token:))
}
// ============================================================================
/// Response from stytch to a request to revoke a given session token.
pub type SessionRevokeResponse {
SessionRevokeResponse(request_id: String, status_code: Int)
}
pub fn session_revoke_response_to_json(
session_revoke_response: SessionRevokeResponse,
) -> json.Json {
let SessionRevokeResponse(request_id:, status_code:) = session_revoke_response
json.object([
#("request_id", json.string(request_id)),
#("status_code", json.int(status_code)),
])
}
pub fn session_revoke_response_decoder() -> decode.Decoder(
SessionRevokeResponse,
) {
use request_id <- decode.field("request_id", decode.string)
use status_code <- decode.field("status_code", decode.int)
decode.success(SessionRevokeResponse(request_id:, status_code:))
}
// ============================================================================
pub type StytchUser {
StytchUser(user_id: String, name: Name, emails: List(Email))
}
pub fn stytch_user_to_json(stytch_user: StytchUser) -> json.Json {
let StytchUser(user_id:, name:, emails:) = stytch_user
json.object([
#("user_id", json.string(user_id)),
#("name", name_to_json(name)),
#("emails", json.array(emails, email_to_json)),
])
}
pub fn stytch_user_decoder() -> decode.Decoder(StytchUser) {
use user_id <- decode.field("user_id", decode.string)
use name <- decode.field("name", name_decoder())
use emails <- decode.field("emails", decode.list(email_decoder()))
decode.success(StytchUser(user_id:, name:, emails:))
}
// ============================================================================
/// Name identifying a user.
pub type Name {
Name(first_name: String, middle_name: String, last_name: String)
}
pub fn name_to_json(name: Name) -> json.Json {
let Name(first_name:, middle_name:, last_name:) = name
json.object([
#("first_name", json.string(first_name)),
#("middle_name", json.string(middle_name)),
#("last_name", json.string(last_name)),
])
}
pub fn name_decoder() -> decode.Decoder(Name) {
use first_name <- decode.field("first_name", decode.string)
use middle_name <- decode.field("middle_name", decode.string)
use last_name <- decode.field("last_name", decode.string)
decode.success(Name(first_name:, middle_name:, last_name:))
}
// ============================================================================
/// Email identifying a user.
/// Stytch separates email_id (not PII) from email and indicates whether the user has verified
/// that they can access that address.
pub type Email {
Email(email_id: String, email: String, verified: Bool)
}
pub fn email_to_json(email: Email) -> json.Json {
let Email(email_id:, email:, verified:) = email
json.object([
#("email_id", json.string(email_id)),
#("email", json.string(email)),
#("verified", json.bool(verified)),
])
}
pub fn email_decoder() -> decode.Decoder(Email) {
use email_id <- decode.field("email_id", decode.string)
use email <- decode.field("email", decode.string)
use verified <- decode.field("verified", decode.bool)
decode.success(Email(email_id:, email:, verified:))
}