From 9db5d90899afc1d15e8ba34d3819ce7d7eddf0cf Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 19 Feb 2024 13:49:46 +0100 Subject: [PATCH] Add support for public clients Closes: https://todo.sr.ht/~emersion/sinwon/19 --- client.go | 3 ++- entity.go | 21 +++++++++++++++------ oauth2.go | 4 ++-- template/manage-client.html | 22 ++++++++++++++++++++++ diff --git a/client.go b/client.go index ba9b59b5e92bb279f2915cd1e8af5d0333adf514..0a60159ab3a82621eeff97a77a14cf04b76c6e44 100644 --- a/client.go +++ b/client.go @@ -69,6 +69,7 @@ client.ClientName = req.PostFormValue("client_name") client.ClientURI = req.PostFormValue("client_uri") client.RedirectURIs = req.PostFormValue("redirect_uris") + isPublic := req.PostFormValue("client_type") == "public" for _, s := range strings.Split(client.RedirectURIs, "\n") { if s == "" { @@ -98,7 +99,7 @@ } var clientSecret string if client.ID == 0 { - clientSecret, err = client.Generate() + clientSecret, err = client.Generate(isPublic) if err != nil { httpError(w, err) return diff --git a/entity.go b/entity.go index 0648661798c559cd20fbf3566aff5064ccf8d30d..400bd46b0dfe44630e0c2ab8ed772776fe8e66eb 100644 --- a/entity.go +++ b/entity.go @@ -137,17 +137,22 @@ ClientName string ClientURI string } -func (client *Client) Generate() (secret string, err error) { +func (client *Client) Generate(isPublic bool) (secret string, err error) { id, err := generateUID() if err != nil { return "", fmt.Errorf("failed to generate client ID: %v", err) } - secret, hash, err := generateSecret() - if err != nil { - return "", fmt.Errorf("failed to generate client secret: %v", err) + client.ClientID = id + + if !isPublic { + var hash []byte + secret, hash, err = generateSecret() + if err != nil { + return "", fmt.Errorf("failed to generate client secret: %v", err) + } + client.ClientSecretHash = hash } - client.ClientID = id - client.ClientSecretHash = hash + return secret, nil } @@ -165,6 +170,10 @@ } func (client *Client) VerifySecret(secret string) bool { return verifyHash(client.ClientSecretHash, secret) +} + +func (client *Client) IsPublic() bool { + return client.ClientSecretHash == nil } type AccessToken struct { diff --git a/oauth2.go b/oauth2.go index 8b8804dff7a568ef33a4a242aa8a81f311c1d70c..38eb74c41fbb30da595a0d1b397e89059860a584 100644 --- a/oauth2.go +++ b/oauth2.go @@ -218,7 +218,7 @@ oauthError(w, fmt.Errorf("failed to fetch client: %v", err)) return } - if client.ClientSecretHash != nil { + if !client.IsPublic() { if !client.VerifySecret(clientSecret) { oauthError(w, &oauth2.Error{ Code: oauth2.ErrorCodeAccessDenied, @@ -320,7 +320,7 @@ var resp oauth2.IntrospectionResp if token != nil { if client == nil { - if client.ClientSecretHash != nil { + if !client.IsPublic() { oauthError(w, &oauth2.Error{ Code: oauth2.ErrorCodeInvalidClient, Description: "Missing client ID and secret", diff --git a/template/manage-client.html b/template/manage-client.html index e73ac17f82b95a5d954940a63cfd71776280d01c..5d785735424e3f94ef70dea78ded97680b99bf6d 100644 --- a/template/manage-client.html +++ b/template/manage-client.html @@ -11,6 +11,28 @@ {{ end }} Name:
Website:
+ Client type: + {{ if .Client.ID }} + {{ if .Client.IsPublic }} + public + {{ else }} + confidential + {{ end }} +
+ {{ else }} +
+ +
+ +
+ {{ end }} + Redirect URIs:

The special URI http://localhost matches all loopback interfaces.
-- 2.48.1