OAuth2 and OpenID Connect (OIDC) client library for MoonBit with support for Authorization Code Flow, Client Credentials, Password Grant, and PKCE
Dependencies
⚠️ ALPHA VERSION This library is currently in alpha stage. APIs may change without notice. Not recommended for production use yet.
{
"deps": {
"ryota0624/oauth2": "*"
}
}let token_url = @oauth2.TokenUrl::new("https://oauth.example.com/token")
let client_id = @oauth2.ClientId::new("your-client-id")
let client_secret = @oauth2.ClientSecret::new("your-client-secret")
let scopes = [@oauth2.Scope::new("read"), @oauth2.Scope::new("write")]
let request = @oauth2.ClientCredentialsRequest::new(
token_url,
client_id,
client_secret,
scopes,
)
let http_client = @oauth2.OAuth2HttpClient::new()
let result = request.execute(http_client)
match result {
Ok(response) => {
let access_token = response.access_token()
println("Access Token: \{access_token}")
}
Err(error) => {
println("Error: \{error.message()}")
}
}// 1. Generate authorization URL
let auth_url = @oauth2.AuthUrl::new("https://oauth.example.com/authorize")
let client_id = @oauth2.ClientId::new("your-client-id")
let redirect_uri = @oauth2.RedirectUrl::new("http://localhost:3000/callback")
let scopes = [@oauth2.Scope::new("openid"), @oauth2.Scope::new("profile")]
let state = @oauth2.generate_csrf_token()
let pkce_verifier = @oauth2.PkceCodeVerifier::new_random()
let pkce_challenge = @oauth2.PkceCodeChallenge::from_verifier_s256(pkce_verifier)
let auth_request = @oauth2.AuthorizationRequest::new_with_pkce(
auth_url,
client_id,
redirect_uri,
scopes,
state,
pkce_challenge,
)
let authorization_url = auth_request.build_authorization_url()
// Redirect user to authorization_url
// 2. Exchange authorization code for token
let token_url = @oauth2.TokenUrl::new("https://oauth.example.com/token")
let client_secret = @oauth2.ClientSecret::new("your-client-secret")
let code = "authorization-code-from-callback"
let token_request = @oauth2.TokenRequest::new_with_pkce(
token_url,
client_id,
client_secret,
code,
redirect_uri,
pkce_verifier,
)
let http_client = @oauth2.OAuth2HttpClient::new()
let result = token_request.execute(http_client)moon test# Start Keycloak and setup test environment
./scripts/setup_keycloak.sh
# Run OAuth2 integration tests
./scripts/test_keycloak_moonbit.sh# Run OIDC verification tests
./scripts/verify_oidc.shtype AccessTokenimpl Eq for AccessTokenimpl Show for AccessTokentype AuthUrlpub struct AuthorizationRequest {
auth_url : AuthUrl
client_id : ClientId
redirect_uri : RedirectUrl
scope : Array[Scope]
state : CsrfToken
response_type : String
pkce_challenge : PkceCodeChallenge?
nonce : Nonce?
}impl Show for AuthorizationRequestfn AuthorizationRequest::new(auth_url : AuthUrl, client_id : ClientId, redirect_uri : RedirectUrl, scope : Array[Scope], state : CsrfToken) -> AuthorizationRequestfn AuthorizationRequest::new_with_pkce(auth_url : AuthUrl, client_id : ClientId, redirect_uri : RedirectUrl, scope : Array[Scope], state : CsrfToken, pkce_challenge : PkceCodeChallenge) -> AuthorizationRequestfn AuthorizationRequest::with_nonce(self : AuthorizationRequest, nonce : Nonce) -> AuthorizationRequestpub struct ClientCredentialsRequest {
token_url : TokenUrl
client_id : ClientId
client_secret : ClientSecret
scope : Array[Scope]
grant_type : String
}impl Show for ClientCredentialsRequestasync fn ClientCredentialsRequest::execute(self : ClientCredentialsRequest, http_client : OAuth2HttpClient) -> Result[TokenResponse, OAuth2Error]fn ClientCredentialsRequest::new(token_url : TokenUrl, client_id : ClientId, client_secret : ClientSecret, scope : Array[Scope]) -> ClientCredentialsRequesttype ClientIdtype ClientSecretimpl Eq for ClientSecretimpl Show for ClientSecrettype CsrfTokenpub(all) enum HttpMethod {
GET
POST
PUT
DELETE
}impl Eq for HttpMethodimpl Show for HttpMethodpub struct HttpRequest {
url : String
http_method : HttpMethod
headers : Map[String, String]
body : String
}impl Show for HttpRequestfn HttpRequest::new(url : String, http_method : HttpMethod, headers : Map[String, String], body : String) -> HttpRequestimpl Show for HttpResponsefn HttpResponse::new(status_code : Int, headers : Map[String, String], body : String) -> HttpResponsetype Noncepub enum OAuth2Error {
InvalidRequest(String)
InvalidClient(String)
InvalidGrant(String)
UnauthorizedClient(String)
UnsupportedGrantType(String)
InvalidScope(String)
AccessDenied(String)
UnsupportedResponseType(String)
ServerError(String)
TemporarilyUnavailable(String)
HttpError(String)
ParseError(String)
Other(String)
}impl Eq for OAuth2Errorimpl Show for OAuth2Errorpub struct OAuth2HttpClient {
debug : Bool
}async fn OAuth2HttpClient::get(self : OAuth2HttpClient, url : String, headers : Map[String, String]) -> Result[HttpResponse, OAuth2Error]async fn OAuth2HttpClient::post(self : OAuth2HttpClient, url : String, headers : Map[String, String], body : String) -> Result[HttpResponse, OAuth2Error]pub struct PasswordRequest {
token_url : TokenUrl
client_id : ClientId
client_secret : ClientSecret?
username : String
password : String
scope : Array[Scope]
grant_type : String
}impl Show for PasswordRequestasync fn PasswordRequest::execute(self : PasswordRequest, http_client : OAuth2HttpClient) -> Result[TokenResponse, OAuth2Error]fn PasswordRequest::new(token_url : TokenUrl, client_id : ClientId, client_secret : ClientSecret?, username : String, password : String, scope : Array[Scope]) -> PasswordRequestimpl Eq for PkceCodeChallengeimpl Show for PkceCodeChallengepub enum PkceCodeChallengeMethod {
Plain
S256
}impl Eq for PkceCodeChallengeMethodimpl Show for PkceCodeChallengeMethodpub struct PkceCodeVerifier {
value : String
}impl Eq for PkceCodeVerifierimpl Show for PkceCodeVerifiertype RedirectUrlimpl Eq for RedirectUrlimpl Show for RedirectUrltype RefreshTokenimpl Eq for RefreshTokenimpl Show for RefreshTokentype Scopepub struct TokenRequest {
token_url : TokenUrl
client_id : ClientId
client_secret : ClientSecret
code : String
redirect_uri : RedirectUrl
grant_type : String
pkce_verifier : PkceCodeVerifier?
}impl Show for TokenRequestasync fn TokenRequest::execute(self : TokenRequest, http_client : OAuth2HttpClient) -> Result[TokenResponse, OAuth2Error]fn TokenRequest::new(token_url : TokenUrl, client_id : ClientId, client_secret : ClientSecret, code : String, redirect_uri : RedirectUrl) -> TokenRequestfn TokenRequest::new_with_pkce(token_url : TokenUrl, client_id : ClientId, client_secret : ClientSecret, code : String, redirect_uri : RedirectUrl, pkce_verifier : PkceCodeVerifier) -> TokenRequestpub struct TokenResponse {
access_token : AccessToken
token_type : String
expires_in : Int?
refresh_token : RefreshToken?
scope : String?
id_token : String?
}impl Show for TokenResponsefn TokenResponse::new(access_token : AccessToken, token_type : String, expires_in : Int?, refresh_token : RefreshToken?, scope : String?, id_token : String?) -> TokenResponsetype TokenUrlfn base64url_encode(s : String) -> Stringfn url_encode(s : String) -> StringInstall
Download zipOAuth2 and OpenID Connect (OIDC) client library for MoonBit with support for Authorization Code Flow, Client Credentials, Password Grant, and PKCE
Dependencies