OAuth 2.0 authorization and token exchange
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

ocaml-linkedin: apply dune fmt

Pure formatting changes from `dune fmt`: doc comment placement moves
from above the binding to below it for `type`s, multi-line `match`
expressions collapse onto one line where they fit, and infix operator
applications pick up spaces (`Soup.($?)` -> `Soup.( $? )`). No
semantic changes.

+44 -28
+37 -28
README.md
··· 21 21 22 22 ## Installation 23 23 24 + Install with opam: 25 + 26 + ```sh 27 + $ opam install oauth 24 28 ``` 25 - opam install oauth 29 + 30 + If opam cannot find the package, it may not yet be released in the public 31 + `opam-repository`. Add the overlay repository, then install it: 32 + 33 + ```sh 34 + $ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git 35 + $ opam update 36 + $ opam install oauth 26 37 ``` 27 38 28 39 ## Usage 29 40 30 41 ```ocaml 31 42 (* 1. Before redirect: generate state and PKCE *) 32 - let redirect_uri = 33 - Oauth.redirect_uri "https://app.com/callback" |> Result.get_ok 34 - in 35 - let state = Oauth.generate_state () in 36 - let verifier = Oauth.generate_code_verifier () in 37 - let challenge = Oauth.code_challenge S256 verifier in 38 - (* Store [state] and [verifier] in the user's session *) 43 + let run http callback_state code = 44 + let redirect_uri = 45 + Oauth.redirect_uri "https://app.com/callback" |> Result.get_ok 46 + in 47 + let state = Oauth.generate_state () in 48 + let verifier = Oauth.generate_code_verifier () in 49 + let challenge = Oauth.code_challenge S256 verifier in 50 + (* Store [state] and [verifier] in the user's session. *) 51 + let _url = 52 + Oauth.authorization_url Github ~client_id:"xxx" ~redirect_uri ~state 53 + ~scope:[ "user:email" ] ~code_challenge:challenge () 54 + in 55 + (* Redirect user to [_url]. *) 39 56 40 - let url = 41 - Oauth.authorization_url Github ~client_id:"xxx" 42 - ~redirect_uri ~state 43 - ~scope:[ "user:email" ] ~code_challenge:challenge () 44 - in 45 - (* Redirect user to [url] *) 46 - 47 - (* 2. On callback: validate state, then exchange code *) 48 - if not (Oauth.validate_state ~expected:state ~actual:callback_state) then 49 - failwith "CSRF state mismatch"; 50 - 51 - let client_auth = 52 - Oauth.Client_auth.basic ~client_id:"xxx" ~client_secret:"yyy" 53 - in 54 - match 55 - Oauth.exchange_code http Github ~client_auth 56 - ~code ~redirect_uri ~code_verifier:verifier () 57 - with 58 - | Ok token -> Printf.printf "Access token: %s\n" token.access_token 59 - | Error e -> Fmt.epr "Error: %a@." Oauth.pp_error e 57 + (* 2. On callback: validate state, then exchange code *) 58 + if not (Oauth.validate_state ~expected:state ~actual:callback_state) then 59 + failwith "CSRF state mismatch"; 60 + let client_auth = 61 + Oauth.Client_auth.basic ~client_id:"xxx" ~client_secret:"yyy" 62 + in 63 + match 64 + Oauth.exchange_code http Github ~client_auth ~code ~redirect_uri 65 + ~code_verifier:verifier () 66 + with 67 + | Ok token -> Printf.printf "Access token: %s\n" token.access_token 68 + | Error e -> Fmt.epr "Error: %a@." Oauth.pp_parse_token_error e 60 69 ``` 61 70 62 71 ## API
+4
dune
··· 1 1 (env 2 2 (dev 3 3 (flags :standard %{dune-warnings}))) 4 + 5 + (mdx 6 + (files README.md) 7 + (libraries oauth fmt))
+2
dune-project
··· 1 1 (lang dune 3.21) 2 + (using mdx 0.4) 2 3 (name oauth) 3 4 4 5 (generate_opam_files true) ··· 31 32 (logs (>= 0.7)) 32 33 (alcotest :with-test) 33 34 (alcobar :with-test) 35 + (mdx :with-test) 34 36 (odoc :with-doc)))
+1
oauth.opam
··· 27 27 "logs" {>= "0.7"} 28 28 "alcotest" {with-test} 29 29 "alcobar" {with-test} 30 + "mdx" {with-test} 30 31 "odoc" {with-doc} 31 32 ] 32 33 build: [