- bonfire.wrap registers a Repeatable Flag as a Cobra StringSlice so Input.Flags returns every repeated --name=value occurrence in order; scalar/bare flags are unaffected (D-19) - wristband.IssueClientCredentials/RejectRedirectURI export the exact random-id/secret/hash and redirect-URI validation RFC 7591 registration already uses, so the fonoteka:oauth-client operator command shares one hash/validation path with DCR (T-08-SECRET-TIMING)
41 lines
1.8 KiB
Go
41 lines
1.8 KiB
Go
// Shared client-issuing primitives used by both RFC 7591 registration
|
|
// (register.go) and the app-owned fonoteka:oauth-client operator command
|
|
// (08-CONTEXT.md D-19; T-08-SECRET-TIMING: "Shared hash/validation path and
|
|
// one-time secret"). Exporting these rather than letting the command
|
|
// re-derive its own random-id/hash/redirect-URI-validation logic keeps
|
|
// exactly one code path responsible for how an OAuth client secret is
|
|
// generated and hashed.
|
|
package wristband
|
|
|
|
// IssueClientCredentials mints a random opaque client_id (16 raw bytes,
|
|
// base64url) and, for every token_endpoint_auth_method other than "none", a
|
|
// client_secret (32 raw bytes) plus its sha256 hex hash -- the identical
|
|
// fixed transform RFC 7591 registration uses (D-04). secret is "" and
|
|
// secretHash is nil for a public ("none") client. The raw secret is
|
|
// returned exactly once; only secretHash is meant to be persisted.
|
|
func IssueClientCredentials(authMethod string) (clientID, secret string, secretHash *string, err error) {
|
|
clientID, err = randomBase64URL(16)
|
|
if err != nil {
|
|
return "", "", nil, err
|
|
}
|
|
if authMethod == "none" {
|
|
return clientID, "", nil, nil
|
|
}
|
|
secret, err = randomBase64URL(32)
|
|
if err != nil {
|
|
return "", "", nil, err
|
|
}
|
|
h := sha256Hex(secret)
|
|
return clientID, secret, &h, nil
|
|
}
|
|
|
|
// RejectRedirectURI is the exported form of the redirect-URI validation
|
|
// RFC 7591 registration already enforces (PHP OAuthClient::rejectRedirectUri):
|
|
// at most 512 characters, a valid URL with scheme+host, https:// or loopback
|
|
// http://127.0.0.1 / http://localhost. It returns "" when uri is accepted,
|
|
// or a human-readable rejection reason otherwise. The operator command
|
|
// shares this exact rule with DCR rather than re-deriving it (D-19).
|
|
func RejectRedirectURI(uri string) string {
|
|
return rejectRedirectURI(uri)
|
|
}
|