this repo has no description
1package oauth
2
3import (
4 "encoding/json"
5 "fmt"
6 "net/url"
7 "slices"
8)
9
10type TokenResponse struct {
11 DpopAuthserverNonce string `json:"-"`
12 AccessToken string `json:"access_token"`
13 RefreshToken string `json:"refresh_token"`
14 ExpiresIn int `json:"expires_in"`
15 Scope string `json:"scope"`
16 Sub string `json:"sub"`
17 TokenType string `json:"token_type"`
18}
19
20type RefreshTokenArgs struct {
21 AuthserverUrl string
22 RefreshToken string
23 DpopPrivateJwk string
24 DpopAuthserverNonce string
25}
26
27type SendParAuthResponse struct {
28 PkceVerifier string
29 State string
30 DpopAuthserverNonce string
31 ExpiresIn float64
32 RequestUri string
33}
34
35type OauthProtectedResource struct {
36 Resource string `json:"resource"`
37 AuthorizationServers []string `json:"authorization_servers"`
38 ScopesSupported []string `json:"scopes_supported"`
39 BearerMethodsSupported []string `json:"bearer_methods_supported"`
40 ResourceDocumentation string `json:"resource_documentation"`
41}
42
43func (opr *OauthProtectedResource) UnmarshalJSON(b []byte) error {
44 type Tmp OauthProtectedResource
45 var tmp Tmp
46
47 if err := json.Unmarshal(b, &tmp); err != nil {
48 return err
49 }
50
51 *opr = OauthProtectedResource(tmp)
52
53 return nil
54}
55
56type OauthAuthorizationMetadata struct {
57 Issuer string `json:"issuer"`
58 RequestParameterSupported bool `json:"request_parameter_supported"`
59 RequestUriParameterSupported bool `json:"request_uri_parameter_supported"`
60 RequireRequestUriRegistration *bool `json:"require_request_uri_registration,omitempty"`
61 ScopesSupported []string `json:"scopes_supported"`
62 SubjectTypesSupported []string `json:"subject_types_supported"`
63 ResponseTypesSupported []string `json:"response_types_supported"`
64 ResponseModesSupported []string `json:"response_modes_supported"`
65 GrantTypesSupported []string `json:"grant_types_supported"`
66 CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
67 UILocalesSupported []string `json:"ui_locales_supported"`
68 DisplayValuesSupported []string `json:"display_values_supported"`
69 RequestObjectSigningAlgValuesSupported []string `json:"request_object_signing_alg_values_supported"`
70 AuthorizationResponseISSParameterSupported bool `json:"authorization_response_iss_parameter_supported"`
71 RequestObjectEncryptionAlgValuesSupported []string `json:"request_object_encryption_alg_values_supported"`
72 RequestObjectEncryptionEncValuesSupported []string `json:"request_object_encryption_enc_values_supported"`
73 JwksUri string `json:"jwks_uri"`
74 AuthorizationEndpoint string `json:"authorization_endpoint"`
75 TokenEndpoint string `json:"token_endpoint"`
76 TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
77 TokenEndpointAuthSigningAlgValuesSupported []string `json:"token_endpoint_auth_signing_alg_values_supported"`
78 RevocationEndpoint string `json:"revocation_endpoint"`
79 IntrospectionEndpoint string `json:"introspection_endpoint"`
80 PushedAuthorizationRequestEndpoint string `json:"pushed_authorization_request_endpoint"`
81 RequirePushedAuthorizationRequests bool `json:"require_pushed_authorization_requests"`
82 DpopSigningAlgValuesSupported []string `json:"dpop_signing_alg_values_supported"`
83 ProtectedResources []string `json:"protected_resources"`
84 ClientIDMetadataDocumentSupported bool `json:"client_id_metadata_document_supported"`
85}
86
87func (oam *OauthAuthorizationMetadata) UnmarshalJSON(b []byte) error {
88 type Tmp OauthAuthorizationMetadata
89 var tmp Tmp
90
91 if err := json.Unmarshal(b, &tmp); err != nil {
92 return err
93 }
94
95 *oam = OauthAuthorizationMetadata(tmp)
96
97 return nil
98}
99
100func (oam *OauthAuthorizationMetadata) Validate(fetch_url *url.URL) error {
101 if fetch_url == nil {
102 return fmt.Errorf("fetch_url was nil")
103 }
104
105 iu, err := url.Parse(oam.Issuer)
106 if err != nil {
107 return err
108 }
109
110 if iu.Hostname() != fetch_url.Hostname() {
111 return fmt.Errorf("issuer hostname does not match fetch url hostname")
112 }
113
114 if iu.Scheme != "https" {
115 return fmt.Errorf("issuer url is not https")
116 }
117
118 if iu.Port() != "" {
119 return fmt.Errorf("issuer port is not empty")
120 }
121
122 if iu.Path != "" && iu.Path != "/" {
123 return fmt.Errorf("issuer path is not /")
124 }
125
126 if iu.RawQuery != "" {
127 return fmt.Errorf("issuer url params are not empty")
128 }
129
130 if !slices.Contains(oam.ResponseTypesSupported, "code") {
131 return fmt.Errorf("`code` is not in response_types_supported")
132 }
133
134 if !slices.Contains(oam.GrantTypesSupported, "authorization_code") {
135 return fmt.Errorf("`authorization_code` is not in grant_types_supported")
136 }
137
138 if !slices.Contains(oam.GrantTypesSupported, "refresh_token") {
139 return fmt.Errorf("`refresh_token` is not in grant_types_supported")
140 }
141
142 if !slices.Contains(oam.CodeChallengeMethodsSupported, "S256") {
143 return fmt.Errorf("`S256` is not in code_challenge_methods_supported")
144 }
145
146 if !slices.Contains(oam.TokenEndpointAuthMethodsSupported, "none") {
147 return fmt.Errorf("`none` is not in token_endpoint_auth_methods_supported")
148 }
149
150 if !slices.Contains(oam.TokenEndpointAuthMethodsSupported, "private_key_jwt") {
151 return fmt.Errorf("`private_key_jwt` is not in token_endpoint_auth_methods_supported")
152 }
153
154 if !slices.Contains(oam.TokenEndpointAuthSigningAlgValuesSupported, "ES256") {
155 return fmt.Errorf("`ES256` is not in token_endpoint_auth_signing_alg_values_supported")
156 }
157
158 if !slices.Contains(oam.ScopesSupported, "atproto") {
159 return fmt.Errorf("`atproto` is not in scopes_supported")
160 }
161
162 if oam.AuthorizationResponseISSParameterSupported != true {
163 return fmt.Errorf("authorization_response_iss_parameter_supported is not true")
164 }
165
166 if oam.PushedAuthorizationRequestEndpoint == "" {
167 return fmt.Errorf("pushed_authorization_request_endpoint is empty")
168 }
169
170 if oam.RequirePushedAuthorizationRequests == false {
171 return fmt.Errorf("require_pushed_authorization_requests is false")
172 }
173
174 if !slices.Contains(oam.DpopSigningAlgValuesSupported, "ES256") {
175 return fmt.Errorf("`ES256` is not in dpop_signing_alg_values_supported")
176 }
177
178 if oam.RequireRequestUriRegistration != nil && *oam.RequireRequestUriRegistration == false {
179 return fmt.Errorf("require_request_uri_registration present in metadata and was false")
180 }
181
182 if oam.ClientIDMetadataDocumentSupported == false {
183 return fmt.Errorf("client_id_metadata_document_supported was false")
184 }
185
186 return nil
187}