this repo has no description
1package oauth 2 3import ( 4 "context" 5 "fmt" 6 "io" 7 "net/http" 8 "net/url" 9 "time" 10) 11 12type OauthClient struct { 13 h *http.Client 14} 15 16type OauthClientArgs struct { 17 h *http.Client 18} 19 20func NewOauthClient(args OauthClientArgs) *OauthClient { 21 if args.h == nil { 22 args.h = &http.Client{ 23 Timeout: 5 * time.Second, 24 } 25 } 26 return &OauthClient{ 27 h: args.h, 28 } 29} 30 31func (o *OauthClient) ResolvePDSAuthServer(ctx context.Context, ustr string) (string, error) { 32 u, err := isSafeAndParsed(ustr) 33 if err != nil { 34 return "", err 35 } 36 37 u.Path = "/.well-known/oauth-protected-resource" 38 39 req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil) 40 if err != nil { 41 return "", fmt.Errorf("error creating request for oauth protected resource: %w", err) 42 } 43 44 resp, err := o.h.Do(req) 45 if err != nil { 46 return "", fmt.Errorf("could not get response from server: %w", err) 47 } 48 defer resp.Body.Close() 49 50 if resp.StatusCode != http.StatusOK { 51 io.Copy(io.Discard, resp.Body) 52 return "", fmt.Errorf("received non-200 response from pds. code was %d", resp.StatusCode) 53 } 54 55 b, err := io.ReadAll(resp.Body) 56 if err != nil { 57 return "", fmt.Errorf("could not read body: %w", err) 58 } 59 60 var resource OauthProtectedResource 61 if err := resource.UnmarshalJSON(b); err != nil { 62 return "", fmt.Errorf("could not unmarshal json: %w", err) 63 } 64 65 if len(resource.AuthorizationServers) == 0 { 66 return "", fmt.Errorf("oauth protected resource contained no authorization servers") 67 } 68 69 return resource.AuthorizationServers[0], nil 70} 71 72func (o *OauthClient) FetchAuthServerMetadata(ctx context.Context, ustr string) (any, error) { 73 u, err := isSafeAndParsed(ustr) 74 if err != nil { 75 return nil, err 76 } 77 78 u.Path = "/.well-known/oauth-authorization-server" 79 80 req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil) 81 if err != nil { 82 return nil, fmt.Errorf("error creating request to fetch auth metadata: %w", err) 83 } 84 85 resp, err := o.h.Do(req) 86 if err != nil { 87 return nil, fmt.Errorf("error getting response for auth metadata: %w", err) 88 } 89 defer resp.Body.Close() 90 91 if resp.StatusCode != http.StatusOK { 92 io.Copy(io.Discard, resp.Body) 93 return nil, fmt.Errorf("received non-200 response from pds. status code was %d", resp.StatusCode) 94 } 95 96 b, err := io.ReadAll(resp.Body) 97 if err != nil { 98 return nil, fmt.Errorf("could not read body for metadata response: %w", err) 99 } 100 101 var metadata OauthAuthorizationMetadata 102 if err := metadata.UnmarshalJSON(b); err != nil { 103 return nil, fmt.Errorf("could not unmarshal metadata: %w", err) 104 } 105 106 if err := metadata.Validate(u); err != nil { 107 return nil, fmt.Errorf("could not validate metadata: %w", err) 108 } 109 110 return metadata, nil 111} 112 113// func ClientAssertionJwt(clientId, authServerUrl string, clientSecretJwk jwk.Key) { 114// clientAssertion := jwt.NewBuilder().Issuer(clientId).Subject(clientId).Audience(authServerUrl).IssuedAt(time.Now().Add() 115// } 116 117func isSafeAndParsed(ustr string) (*url.URL, error) { 118 u, err := url.Parse(ustr) 119 if err != nil { 120 return nil, err 121 } 122 123 if u.Scheme != "https" { 124 return nil, fmt.Errorf("input url is not https") 125 } 126 127 return u, nil 128}