M client.go => client.go +1 -1
@@ 110,7 110,7 @@ func (c *Client) doJSON(req *http.Request, data interface{}) error {
return fmt.Errorf("oauth2: invalid token response MIME type %q", mediaType)
}
- if resp.StatusCode != http.StatusOK {
+ if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
var errorData Error
if err := json.NewDecoder(resp.Body).Decode(&errorData); err != nil {
return err
A client_reg.go => client_reg.go +81 -0
@@ 0,0 1,81 @@
+package oauth2
+
+import (
+ "bytes"
+ "encoding/json"
+ "net/http"
+ "strings"
+ "time"
+)
+
+// ClientMetadata contains registered client metadata defined in RFC 7591.
+type ClientMetadata struct {
+ RedirectURIs []string `json:"redirect_uris,omitempty"`
+ TokenEndpointAuthMethod AuthMethod `json:"token_endpoint_auth_method,omitempty"`
+ GrantTypes []GrantType `json:"grant_types,omitempty"`
+ ResponseTypes []ResponseType `json:"response_types,omitempty"`
+ ClientName string `json:"client_name,omitempty"`
+ ClientURI string `json:"client_uri,omitempty"`
+ LogoURI string `json:"logo_uri,omitempty"`
+ Scope []string `json:"-"`
+ Contacts []string `json:"contacts,omitempty"`
+ TOSURI string `json:"tos_uri,omitempty"`
+ PolicyURI string `json:"policy_uri,omitempty"`
+ JWKSURI string `json:"jwks_uri,omitempty"`
+ JWKS struct{} `json:"jwks,omitempty"` // TODO
+ SoftwareID string `json:"software_id,omitempty"`
+ SoftwareVersion string `json:"software_version,omitempty"`
+}
+
+// RegisterOptions contains optional parameters for client registration.
+type RegisterOptions struct {
+ TokenResp *TokenResp
+}
+
+// RegisterResp contains data returned by the client registration endpoint.
+type RegisterResp struct {
+ ClientID string `json:"client_id"`
+ ClientSecret string `json:"client_secret,omitempty"`
+ ClientIDIssuedAt time.Time `json:"-"`
+ ClientSecretExpiresAt time.Time `json:"-"`
+}
+
+// Register registers a new OAuth client.
+//
+// See RFC 7591 section 3.
+func (c *Client) Register(metadata *ClientMetadata, options *RegisterOptions) (*RegisterResp, error) {
+ reqData := struct {
+ *ClientMetadata
+ ScopeStr string `json:"scope,omitempty"`
+ }{
+ ClientMetadata: metadata,
+ ScopeStr: strings.Join(metadata.Scope, " "),
+ }
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(&reqData); err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest(http.MethodPost, c.Server.RegistrationEndpoint, &buf)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", "application/json")
+ if options != nil && options.TokenResp != nil {
+ options.TokenResp.SetAuthHeader(req.Header)
+ }
+
+ var respData struct {
+ RegisterResp
+ ClientIDIssuedAtUnix int64 `json:"client_id_issued_at,omitempty"`
+ ClientSecretExpiresAtUnix int64 `json:"client_secret_expires_at"`
+ }
+ if err := c.doJSON(req, &respData); err != nil {
+ return nil, err
+ }
+ if respData.ClientIDIssuedAtUnix != 0 {
+ respData.ClientIDIssuedAt = time.Unix(respData.ClientIDIssuedAtUnix, 0)
+ }
+ respData.ClientSecretExpiresAt = time.Unix(respData.ClientSecretExpiresAtUnix, 0)
+ return &respData.RegisterResp, nil
+}
M oauth2.go => oauth2.go +6 -19
@@ 42,25 42,6 @@ type ServerMetadata struct {
DeviceAuthorizationEndpoint string `json:"device_authorization_endpoint,omitempty"`
}
-// ClientMetadata contains registered client metadata defined in RFC 7591.
-type ClientMetadata struct {
- RedirectURIs []string `json:"redirect_uris,omitempty"`
- TokenEndpointAuthMethod AuthMethod `json:"token_endpoint_auth_method,omitempty"`
- GrantTypes []GrantType `json:"grant_types,omitempty"`
- ResponseTypes []ResponseType `json:"response_types,omitempty"`
- ClientName string `json:"client_name,omitempty"`
- ClientURI string `json:"client_uri,omitempty"`
- LogoURI string `json:"logo_uri,omitempty"`
- Scope []string `json:"-"`
- Contacts []string `json:"contacts,omitempty"`
- TOSURI string `json:"tos_uri,omitempty"`
- PolicyURI string `json:"policy_uri,omitempty"`
- JWKSURI string `json:"jwks_uri,omitempty"`
- JWKS struct{} `json:"jwks,omitempty"` // TODO
- SoftwareID string `json:"software_id,omitempty"`
- SoftwareVersion string `json:"software_version,omitempty"`
-}
-
// ResponseType is the desired response for the authorization endpoint.
//
// See RFC 7591 section 2.
@@ 200,6 181,12 @@ const (
ErrorCodeAuthorisationPending ErrorCode = "authorization_pending"
ErrorCodeSlowDown ErrorCode = "slow_down"
ErrorCodeExpiredToken ErrorCode = "expired_token"
+
+ // RFC 7591 section 3.2.2
+ ErrorCodeInvalidRedirectURI ErrorCode = "invalid_redirect_uri"
+ ErrorCodeInvalidClientMetadata ErrorCode = "invalid_client_metadata"
+ ErrorCodeInvalidSoftwareStatement ErrorCode = "invalid_software_statement"
+ ErrorCodeUnapprovedSoftwareStatement ErrorCode = "unapproved_software_statement"
)
// Error is an OAuth 2.0 error returned by the server.