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