oauth#
Generic OAuth 2.0 authorization and token exchange for OCaml.
Overview#
Implements the OAuth 2.0 Authorization Code grant (RFC 6749) with PKCE support (RFC 7636). Provides state generation for CSRF protection, authorization URL construction, and token exchange/refresh. Supports multiple providers out of the box: GitHub, Google, GitLab, and custom providers.
Features#
- Multi-provider -- GitHub, Google, GitLab, and custom OAuth providers
- PKCE -- RFC 7636 code challenge/verifier for native apps
- State validation -- Constant-time CSRF state comparison
- Token exchange -- Makes HTTP calls via
Requests.t - Token refresh -- Automatic refresh token handling
- Userinfo parsing -- Provider-specific user profile parsing
- Redirect URI validation -- HTTPS enforcement, no fragments (RFC 8252)
Installation#
Install with opam:
$ opam install oauth
If opam cannot find the package, it may not yet be released in the public
opam-repository. Add the overlay repository, then install it:
$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install oauth
Usage#
(* 1. Before redirect: generate state and PKCE *)
let run http callback_state code =
let redirect_uri =
Oauth.redirect_uri "https://app.com/callback" |> Result.get_ok
in
let state = Oauth.generate_state () in
let verifier = Oauth.generate_code_verifier () in
let challenge = Oauth.code_challenge S256 verifier in
(* Store [state] and [verifier] in the user's session. *)
let _url =
Oauth.authorization_url Github ~client_id:"xxx" ~redirect_uri ~state
~scope:[ "user:email" ] ~code_challenge:challenge ()
in
(* Redirect user to [_url]. *)
(* 2. On callback: validate state, then exchange code *)
if not (Oauth.validate_state ~expected:state ~actual:callback_state) then
failwith "CSRF state mismatch";
let client_auth =
Oauth.Client_auth.basic ~client_id:"xxx" ~client_secret:"yyy"
in
match
Oauth.exchange_code http Github ~client_auth ~code ~redirect_uri
~code_verifier:verifier ()
with
| Ok token -> Printf.printf "Access token: %s\n" token.access_token
| Error e -> Fmt.epr "Error: %a@." Oauth.pp_parse_token_error e
API#
Providers#
Oauth.Github/Google/Gitlab-- Built-in providersOauth.custom_provider-- Define a custom OAuth provider (validates HTTPS)
Authorization#
Oauth.authorization_url-- Build provider-specific authorization URLOauth.generate_state-- Cryptographically secure CSRF stateOauth.validate_state-- Constant-time state comparisonOauth.redirect_uri-- Validated redirect URI (HTTPS, no fragments)
PKCE#
Oauth.generate_code_verifier-- Random code verifierOauth.code_challenge-- S256 code challenge from verifier
Token Exchange#
Oauth.exchange_code-- Exchange authorization code for tokens (HTTP POST)Oauth.refresh_token-- Refresh an expired access token (HTTP POST)
Userinfo#
Oauth.parse_userinfo-- Parse provider-specific user profileOauth.parse_github_emails-- Get verified primary email from GitHub
Standards#
- RFC 6749 -- OAuth 2.0
- RFC 7636 -- PKCE
- RFC 8252 -- OAuth for Native Apps
- RFC 6750 -- Bearer Token Usage
Licence#
ISC