1package server
2
3import (
4 "fmt"
5
6 "github.com/Azure/go-autorest/autorest/to"
7 "github.com/labstack/echo/v4"
8)
9
10var (
11 CocoonSupportedScopes = []string{
12 "atproto",
13 "transition:email",
14 "transition:generic",
15 "transition:chat.bsky",
16 }
17)
18
19type OauthAuthorizationMetadata struct {
20 Issuer string `json:"issuer"`
21 RequestParameterSupported bool `json:"request_parameter_supported"`
22 RequestUriParameterSupported bool `json:"request_uri_parameter_supported"`
23 RequireRequestUriRegistration *bool `json:"require_request_uri_registration,omitempty"`
24 ScopesSupported []string `json:"scopes_supported"`
25 SubjectTypesSupported []string `json:"subject_types_supported"`
26 ResponseTypesSupported []string `json:"response_types_supported"`
27 ResponseModesSupported []string `json:"response_modes_supported"`
28 GrantTypesSupported []string `json:"grant_types_supported"`
29 CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
30 UILocalesSupported []string `json:"ui_locales_supported"`
31 DisplayValuesSupported []string `json:"display_values_supported"`
32 RequestObjectSigningAlgValuesSupported []string `json:"request_object_signing_alg_values_supported"`
33 AuthorizationResponseISSParameterSupported bool `json:"authorization_response_iss_parameter_supported"`
34 RequestObjectEncryptionAlgValuesSupported []string `json:"request_object_encryption_alg_values_supported"`
35 RequestObjectEncryptionEncValuesSupported []string `json:"request_object_encryption_enc_values_supported"`
36 JwksUri string `json:"jwks_uri"`
37 AuthorizationEndpoint string `json:"authorization_endpoint"`
38 TokenEndpoint string `json:"token_endpoint"`
39 TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
40 TokenEndpointAuthSigningAlgValuesSupported []string `json:"token_endpoint_auth_signing_alg_values_supported"`
41 RevocationEndpoint string `json:"revocation_endpoint"`
42 IntrospectionEndpoint string `json:"introspection_endpoint"`
43 PushedAuthorizationRequestEndpoint string `json:"pushed_authorization_request_endpoint"`
44 RequirePushedAuthorizationRequests bool `json:"require_pushed_authorization_requests"`
45 DpopSigningAlgValuesSupported []string `json:"dpop_signing_alg_values_supported"`
46 ProtectedResources []string `json:"protected_resources"`
47 ClientIDMetadataDocumentSupported bool `json:"client_id_metadata_document_supported"`
48}
49
50func (s *Server) handleWellKnown(e echo.Context) error {
51 return e.JSON(200, map[string]any{
52 "@context": []string{
53 "https://www.w3.org/ns/did/v1",
54 },
55 "id": s.config.Did,
56 "service": []map[string]string{
57 {
58 "id": "#atproto_pds",
59 "type": "AtprotoPersonalDataServer",
60 "serviceEndpoint": "https://" + s.config.Hostname,
61 },
62 },
63 })
64}
65
66func (s *Server) handleOauthProtectedResource(e echo.Context) error {
67 return e.JSON(200, map[string]any{
68 "resource": "https://" + s.config.Hostname,
69 "authorization_servers": []string{
70 "https://" + s.config.Hostname,
71 },
72 "scopes_supported": []string{},
73 "bearer_methods_supported": []string{"header"},
74 "resource_documentation": "https://atproto.com",
75 })
76}
77
78func (s *Server) handleOauthAuthorizationServer(e echo.Context) error {
79 return e.JSON(200, OauthAuthorizationMetadata{
80 Issuer: "https://" + s.config.Hostname,
81 RequestParameterSupported: true,
82 RequestUriParameterSupported: true,
83 RequireRequestUriRegistration: to.BoolPtr(true),
84 ScopesSupported: CocoonSupportedScopes,
85 SubjectTypesSupported: []string{"public"},
86 ResponseTypesSupported: []string{"code"},
87 ResponseModesSupported: []string{"query", "fragment", "form_post"},
88 GrantTypesSupported: []string{"authorization_code", "refresh_token"},
89 CodeChallengeMethodsSupported: []string{"S256"},
90 UILocalesSupported: []string{"en-US"},
91 DisplayValuesSupported: []string{"page", "popup", "touch"},
92 RequestObjectSigningAlgValuesSupported: []string{"ES256"}, // only es256 for now...
93 AuthorizationResponseISSParameterSupported: true,
94 RequestObjectEncryptionAlgValuesSupported: []string{},
95 RequestObjectEncryptionEncValuesSupported: []string{},
96 JwksUri: fmt.Sprintf("https://%s/oauth/jwks", s.config.Hostname),
97 AuthorizationEndpoint: fmt.Sprintf("https://%s/oauth/authorize", s.config.Hostname),
98 TokenEndpoint: fmt.Sprintf("https://%s/oauth/token", s.config.Hostname),
99 TokenEndpointAuthMethodsSupported: []string{"none", "private_key_jwt"},
100 TokenEndpointAuthSigningAlgValuesSupported: []string{"ES256"}, // Same as above, just es256
101 RevocationEndpoint: fmt.Sprintf("https://%s/oauth/revoke", s.config.Hostname),
102 IntrospectionEndpoint: fmt.Sprintf("https://%s/oauth/introspect", s.config.Hostname),
103 PushedAuthorizationRequestEndpoint: fmt.Sprintf("https://%s/oauth/par", s.config.Hostname),
104 RequirePushedAuthorizationRequests: true,
105 DpopSigningAlgValuesSupported: []string{"ES256"}, // again same as above
106 ProtectedResources: []string{"https://" + s.config.Hostname},
107 ClientIDMetadataDocumentSupported: true,
108 })
109}