Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
clients.sx (RFC 6749 §2) — confidential clients must present the correct secret at the token endpoint (wrong → invalid_client); public clients are identified but not authenticated; redirect_uris are pre-registered and checked by exact-match valid_redirect (§3.1.2.2 + Security BCP). Standalone module for now; wiring confidential-client auth into oauth exchange is a follow-up. New tests/clients.sx. 149/149. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
109 lines
4.6 KiB
Plaintext
109 lines
4.6 KiB
Plaintext
;; identity/tests/clients.sx — OAuth client registry: registration,
|
|
;; public vs confidential authentication, and redirect_uri allow-listing.
|
|
|
|
(define id-clients-test-count 0)
|
|
(define id-clients-test-pass 0)
|
|
(define id-clients-test-fails (list))
|
|
|
|
(define
|
|
id-clients-test
|
|
(fn
|
|
(name actual expected)
|
|
(set! id-clients-test-count (+ id-clients-test-count 1))
|
|
(if
|
|
(= actual expected)
|
|
(set! id-clients-test-pass (+ id-clients-test-pass 1))
|
|
(append! id-clients-test-fails {:name name :expected expected :actual actual}))))
|
|
|
|
(define idc-ev erlang-eval-ast)
|
|
(define idcnm (fn (v) (get v :name)))
|
|
|
|
(identity-load-clients!)
|
|
|
|
;; ── registration + lookup ────────────────────────────────────────
|
|
|
|
(id-clients-test
|
|
"a registered client looks up its type"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n identity_clients:register(C, app1, confidential, s3cret, [uri1]),\n case identity_clients:lookup(C, app1) of\n {ok, Type, _} -> Type;\n {error, W} -> W\n end"))
|
|
"confidential")
|
|
|
|
(id-clients-test
|
|
"registering the same client twice is an error"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n identity_clients:register(C, app1, confidential, s3cret, [uri1]),\n case identity_clients:register(C, app1, public, none, [uri1]) of\n ok -> ok;\n {error, W} -> W\n end"))
|
|
"exists")
|
|
|
|
(id-clients-test
|
|
"looking up an unregistered client is unknown_client"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n case identity_clients:lookup(C, ghost) of\n {ok, _, _} -> found;\n {error, W} -> W\n end"))
|
|
"unknown_client")
|
|
|
|
;; ── confidential client authentication ───────────────────────────
|
|
|
|
(id-clients-test
|
|
"a confidential client authenticates with the right secret"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n identity_clients:register(C, app1, confidential, s3cret, [uri1]),\n case identity_clients:authenticate(C, app1, s3cret) of\n {ok, Kind} -> Kind;\n {error, W} -> W\n end"))
|
|
"confidential")
|
|
|
|
(id-clients-test
|
|
"a confidential client with the wrong secret is invalid_client"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n identity_clients:register(C, app1, confidential, s3cret, [uri1]),\n case identity_clients:authenticate(C, app1, wrongsecret) of\n {ok, _} -> accepted;\n {error, W} -> W\n end"))
|
|
"invalid_client")
|
|
|
|
(id-clients-test
|
|
"a public client needs no secret to authenticate"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n identity_clients:register(C, spa, public, none, [uri1]),\n case identity_clients:authenticate(C, spa, anything) of\n {ok, Kind} -> Kind;\n {error, W} -> W\n end"))
|
|
"public")
|
|
|
|
(id-clients-test
|
|
"authenticating an unknown client is unknown_client"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n case identity_clients:authenticate(C, ghost, x) of\n {ok, _} -> accepted;\n {error, W} -> W\n end"))
|
|
"unknown_client")
|
|
|
|
;; ── redirect_uri allow-listing ───────────────────────────────────
|
|
|
|
(id-clients-test
|
|
"a registered redirect_uri is valid"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n identity_clients:register(C, app1, confidential, s3cret, [uri1, uri2]),\n case identity_clients:valid_redirect(C, app1, uri1) of\n true -> yes;\n false -> no\n end"))
|
|
"yes")
|
|
|
|
(id-clients-test
|
|
"a second registered redirect_uri is also valid"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n identity_clients:register(C, app1, confidential, s3cret, [uri1, uri2]),\n case identity_clients:valid_redirect(C, app1, uri2) of\n true -> yes;\n false -> no\n end"))
|
|
"yes")
|
|
|
|
(id-clients-test
|
|
"an unregistered redirect_uri is rejected"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n identity_clients:register(C, app1, confidential, s3cret, [uri1]),\n case identity_clients:valid_redirect(C, app1, evil_uri) of\n true -> yes;\n false -> no\n end"))
|
|
"no")
|
|
|
|
(id-clients-test
|
|
"redirect validation for an unknown client is rejected"
|
|
(idcnm
|
|
(idc-ev
|
|
"C = identity_clients:start(),\n case identity_clients:valid_redirect(C, ghost, uri1) of\n true -> yes;\n false -> no\n end"))
|
|
"no")
|
|
|
|
(define
|
|
id-clients-test-summary
|
|
(str "clients " id-clients-test-pass "/" id-clients-test-count))
|