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