1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
package models
import (
"crypto/rand"
"crypto/sha256"
"crypto/subtle"
"encoding/base64"
"fmt"
)
const (
DEVICE_CODE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code"
)
type AuthorizationRequest struct {
Challenge string `url:"code_challenge" form:"code_challenge" json:"code_challenge"` // RFC7636
ChallengeMethod PKCEChallengeType `url:"code_challenge_method" form:"code_challenge_method" json:"code_challenge_method"` // RFC7636
ClientId string `url:"client_id" form:"client_id" json:"client_id"`
Scope string `url:"scope" form:"scope" json:"scope"`
}
type DeviceAuthorizationResponse struct {
DeviceCode string `json:"device_code"` // REQUIRED
UserCode string `json:"user_code"` // REQUIRED
VerificationUri string `json:"verification_uri"` // REQUIRED
VerificationUriComplete string `json:"verification_uri_complete,omitempty"`
ExpiresIn int `json:"expires_in,omitempty"`
Interval int `json:"interval,omitempty"`
}
type DeviceAccessTokenRequest struct {
GrantType string `url:"grant_type" form:"grant_type" json:"grant_type"`
DeviceCode string `url:"device_code" form:"device_code" json:"device_code"`
ClientId string `url:"client_id" form:"client_id" json:"client_id"`
CodeVerifier string `url:"code_verifier" form:"code_verifier" json:"code_verifier"`
}
type AccessTokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"` // Must be Bearer
ExpiresIn string `json:"expires_in,omitempty"` // Lifetime in seconds
RefreshToken string `json:"refresh_token,omitempty"`
Scope string `json:"scope,omitempty"`
}
type AuthorizationError string
const (
ErrInvalidRequest AuthorizationError = "invalid_request"
ErrInvalidClient = "invalid_client"
ErrInvalidGrant = "invalid_grant"
ErrUnauthorizedClient = "unauthorized_client"
ErrUnsupportedGrantType = "unsupported_grant_type"
ErrInvalidScope = "invalid_scope"
ErrAuthorizationPending = "authorization_pending" // RFC7636
ErrSlowDown = "slow_down" // RFC7636
ErrAccessDenied = "access_denied" // RFC7636
ErrExpiredToken = "expired_token" // RFC7636
)
type Oauth2Error struct {
Type AuthorizationError `json:"error"`
Description string `json:"error_description,omitempty"`
Uri string `json:"error_uri,omitempty"`
}
func (e Oauth2Error) Error() string {
if e.Description == "" {
return fmt.Sprintf("Oauth2Error: %s", e.Type)
} else {
return fmt.Sprintf("Oauth2Error: %s %s", e.Type, e.Description)
}
}
type PKCEChallengeType string
const (
ChallengePlain PKCEChallengeType = "plain"
ChallengeS256 = "S256"
)
type PKCEChallenge struct {
Verifier string
}
func NewPKCEChallenge() (*PKCEChallenge, error) {
buf := make([]byte, 32)
if _, err := rand.Read(buf); err != nil {
return nil, err
}
return &PKCEChallenge{
Verifier: base64.URLEncoding.EncodeToString(buf),
}, nil
}
func (c *PKCEChallenge) Challenge() string {
hash := sha256.Sum256([]byte(c.Verifier))
return base64.URLEncoding.EncodeToString(hash[:])
}
func (c *PKCEChallenge) EqualString(o string) bool {
return subtle.ConstantTimeCompare([]byte(o), []byte(c.Challenge())) != 1
}
const (
GrantTypeAuthCode = "authorization_code" // RFC7591
GrantTypeImplicit = "implicit" // RFC7591
GrantTypePassword = "password" // RFC7591
GrantTypeClientCreds = "client_credentials" // RFC7591
GrantTypeRefreshToken = "refresh_token" // RFC7591
GrantTypeBearerJwt = "urn:ietf:params:oauth:grant-type:jwt-bearer" // RFC7591
GrantTypeBearerSaml = "urn:ietf:params:oauth:grant-type:saml2-bearer" // RFC7591
GrantTypeDevice = "urn:ietf:params:oauth:grant-type:device_code" // RFC8628
ResponseTypeCode = "code" // RFC7591
ResponseTypeToken = "token" // RFC7591
ResponseModeQuery = "query" // RFC7591
ResponseModeFragment = "fragment" // RFC7591
ResponseModeFormPost = "form_post" // RFC7591
ChallengeTypePlain = "plain" // RFC7636
ChallengeTypeSHA256 = "S256" // RFC7636
Oauth2MetadataPath = "/.well-known/oauth-authorization-server"
Oauth2MetadataCompatPath = "/.well-known/openid-configuration"
)
// All options are required unless omitempty
type OauthDiscoveryMetadata struct {
Issuer string `json:"issuer"` // RFC88414, https url w/no query/fragment
AuthorizationEndpoint string `json:"authorization_endpoint"` // RFC88414
TokenEndpoint string `json:"token_endpoint"` // RFC88414
SupportedResponseTypes []string `json:"response_types_supported"` // RFC88414
JWKSUri string `json:"jwks_uri,omitempty"` // RFC88414
RegistrationEndpoint string `json:"registration_endpoint,omitempty"` // RFC88414
SupportedScopes []string `json:"scopes_supported,omitempty"` // RFC88414
SupportedResponseModes []string `json:"response_modes_supported,omitempty"` // RFC88414
SupportedGrantTypes []string `json:"grant_types_supported,omitempty"` // RFC88414, default: authorization_code, implicit
SupportedAuthMethods []string `json:"token_endpoint_auth_methods_supported,omitempty"` // RFC88414
SupportedSigningAlgs []string `json:"token_endpoint_auth_signing_alg_values_supported,omitempty"` // RFC88414
SupportedUILocales []string `json:"ui_locales_supported,omitempty"` // RFC88414, RFC5646 codes
PolicyUri string `json:"op_policy_uri,omitempty"` // RFC88414
TosUri string `json:"op_tos_uri,omitempty"` // RFC88414
RevocationEndpoint string `json:"revocation_endpoint,omitempty"` // RFC88414
SupportedRevocationAuthMethods []string `json:"revocation_endpoint_auth_methods_supported,omitempty"` // RFC88414
SupportedRevocationSigningAlgs []string `json:"revocation_endpoint_auth_signing_alg_values_supported,omitempty"` // RFC88414
IntrospectionEndpoint string `json:"introspection_endpoint,omitempty"` // RFC88414
SupportedIntrospectionAuthMethods []string `json:"introspection_endpoint_auth_methods_supported,omitempty"` // RFC88414
SupportedIntrospectionSigningAlgs []string `json:"introspection_endpoint_auth_signing_alg_values_supported,omitempty"` // RFC88414
SupportedChallengeCodeMethods []string `json:"code_challenge_methods_supported,omitempty"` // RFC88414
ServiceDocumentation string `json:"service_documentation,omitempty"` // RFC88414
DeviceAuthorizationEndpoint string `json:"device_authorization_endpoint,omitempty"` // RFC8628
}
|