···115115 let%lwt _ =
116116 Sequencer.sequence_sync ctx.db ~did ~rev:commit.rev ~blocks ()
117117 in
118118- let access_jwt, refresh_jwt = Auth.generate_jwt did in
118118+ let access_jwt, refresh_jwt = Jwt.generate_jwt did in
119119 Dream.json @@ Yojson.Safe.to_string
120120 @@ response_to_yojson {access_jwt; refresh_jwt; did; handle= input.handle} )
+1-1
pegasus/lib/api/server/createSession.ml
···2626 Lwt_result.catch @@ fun () -> Data_store.try_login ~id ~password db
2727 with
2828 | Ok (Some actor) when Auth.verify_auth auth actor.did ->
2929- let access_jwt, refresh_jwt = Auth.generate_jwt actor.did in
2929+ let access_jwt, refresh_jwt = Jwt.generate_jwt actor.did in
3030 let active, status =
3131 match actor.deactivated_at with
3232 | None ->
+3-2
pegasus/lib/api/server/getServiceAuth.ml
···1010 | _ ->
1111 Errors.invalid_request "missing aud or lxm"
1212 in
1313- let%lwt signing_key =
1313+ let%lwt signing_multikey =
1414 match%lwt Data_store.get_actor_by_identifier did db with
1515 | Some {signing_key; _} ->
1616 Lwt.return signing_key
1717 | None ->
1818 Errors.internal_error ~msg:"actor not found" ()
1919 in
2020- let token = Auth.generate_service_jwt ~did ~aud ~lxm ~signing_key in
2020+ let signing_key = Kleidos.parse_multikey_str signing_multikey in
2121+ let token = Jwt.generate_service_jwt ~did ~aud ~lxm ~signing_key in
2122 Dream.json @@ Yojson.Safe.to_string @@ response_to_yojson {token} )
+1-1
pegasus/lib/api/server/refreshSession.ml
···1818 in
1919 let%lwt () = Data_store.revoke_token ~did ~jti db in
2020 let%lwt {handle; did; active; status; _} = Auth.get_session_info did db in
2121- let access_jwt, refresh_jwt = Auth.generate_jwt did in
2121+ let access_jwt, refresh_jwt = Jwt.generate_jwt did in
2222 Dream.json @@ Yojson.Safe.to_string
2323 @@ response_to_yojson
2424 {access_jwt; refresh_jwt; handle; did; active; status} )
+15-76
pegasus/lib/auth.ml
···11type t = (module Rapper_helper.CONNECTION)
2233-type symmetric_jwt =
44- {scope: string; aud: string; sub: string; iat: int; exp: int; jti: string}
55-63type session_info =
74 { handle: string
85 ; did: string
···1916 | Access of {did: string}
2017 | Refresh of {did: string; jti: string}
21182222-let generate_jwt did =
2323- let now_s = int_of_float (Unix.gettimeofday ()) in
2424- let access_exp = now_s + (60 * 60 * 3) in
2525- let refresh_exp = now_s + (60 * 60 * 24 * 7) in
2626- let jti = Uuidm.v4_gen (Random.get_state ()) () |> Uuidm.to_string in
2727- let access =
2828- match
2929- Jwto.encode Jwto.HS256 Env.jwt_secret
3030- [ ("scope", "com.atproto.access")
3131- ; ("aud", Env.did)
3232- ; ("sub", did)
3333- ; ("iat", Int.to_string now_s)
3434- ; ("exp", Int.to_string access_exp)
3535- ; ("jti", jti) ]
3636- with
3737- | Ok token ->
3838- token
3939- | Error err ->
4040- failwith err
4141- in
4242- let refresh =
4343- match
4444- Jwto.encode Jwto.HS256 Env.jwt_secret
4545- [ ("scope", "com.atproto.refresh")
4646- ; ("aud", Env.did)
4747- ; ("sub", did)
4848- ; ("iat", Int.to_string now_s)
4949- ; ("exp", Int.to_string refresh_exp)
5050- ; ("jti", jti) ]
5151- with
5252- | Ok token ->
5353- token
5454- | Error err ->
5555- failwith err
5656- in
5757- (access, refresh)
5858-5959-let generate_service_jwt ~did ~aud ~lxm ~signing_key =
6060- let now_s = int_of_float (Unix.gettimeofday ()) in
6161- let exp = now_s + (60 * 5) in
6262- match
6363- Jwto.encode Jwto.HS256 signing_key
6464- [("iss", did); ("aud", aud); ("lxm", lxm); ("exp", Int.to_string exp)]
6565- with
6666- | Ok token ->
6767- token
6868- | Error err ->
6969- failwith err
7070-7119let verify_bearer_jwt t token expected_scope =
7272- match Jwto.decode_and_verify Env.jwt_secret token with
2020+ match Jwt.verify_jwt token Env.jwt_key with
7321 | Error err ->
7422 Lwt.return_error err
7575- | Ok jwt ->
7676- let payload = Jwto.get_payload jwt in
2323+ | Ok (_, payload) -> (
2424+ try
7725 let now_s = int_of_float (Unix.gettimeofday ()) in
7878- let scope = List.assoc_opt "scope" payload |> Option.value ~default:"" in
7979- let aud = List.assoc_opt "aud" payload |> Option.value ~default:"" in
8080- let sub = List.assoc_opt "sub" payload |> Option.value ~default:"" in
8181- let iat =
8282- List.assoc_opt "iat" payload
8383- |> Option.map int_of_string
8484- |> Option.value ~default:max_int
8585- in
8686- let exp =
8787- List.assoc_opt "exp" payload
8888- |> Option.map int_of_string |> Option.value ~default:0
8989- in
9090- let jti = List.assoc_opt "jti" payload |> Option.value ~default:"" in
9191- if aud <> Env.did then Lwt.return_error "invalid aud"
9292- else if sub = "" then Lwt.return_error "missing sub"
9393- else if now_s < iat then Lwt.return_error "token issued in the future"
9494- else if now_s > exp then Lwt.return_error "expired token"
9595- else if scope <> expected_scope then Lwt.return_error "invalid scope"
9696- else if jti = "" then Lwt.return_error "missing jti"
2626+ let jwt = Jwt.symmetric_jwt_of_yojson payload |> Result.get_ok in
2727+ if jwt.aud <> Env.did then Lwt.return_error "invalid aud"
2828+ else if jwt.sub = "" then Lwt.return_error "missing sub"
2929+ else if now_s < jwt.iat then Lwt.return_error "token issued in the future"
3030+ else if now_s > jwt.exp then Lwt.return_error "expired token"
3131+ else if jwt.scope <> expected_scope then Lwt.return_error "invalid scope"
3232+ else if jwt.jti = "" then Lwt.return_error "missing jti"
9733 else
9898- let%lwt revoked_at = Data_store.is_token_revoked t ~did:sub ~jti in
3434+ let%lwt revoked_at =
3535+ Data_store.is_token_revoked t ~did:jwt.sub ~jti:jwt.jti
3636+ in
9937 if revoked_at <> None then Lwt.return_error "token revoked"
100100- else Lwt.return_ok {scope; aud; sub; iat; exp; jti}
3838+ else Lwt.return_ok jwt
3939+ with _ -> Lwt.return_error "invalid token format" )
1014010241let verify_auth ?(refresh = false) credentials did =
10342 match credentials with