MCPcopy Index your code
hub / github.com/coder/coder / ExtractOAuth2

Function ExtractOAuth2

coderd/httpmw/oauth2.go:48–222  ·  view source on GitHub ↗

ExtractOAuth2 is a middleware for automatically redirecting to OAuth URLs, and handling the exchange inbound. Any route that does not have a "code" URL parameter will be redirected. AuthURLOpts are passed to the AuthCodeURL function. If this is nil, the default option oauth2.AccessTypeOffline will b

(config promoauth.OAuth2Config, client *http.Client, cookieCfg codersdk.HTTPCookieConfig, authURLOpts map[string]string, pkceMethods []promoauth.Oauth2PKCEChallengeMethod)

Source from the content-addressed store, hash-verified

46// which PKCE methods are supported by the OAuth2 provider. If empty,
47// PKCE will not be used.
48func ExtractOAuth2(config promoauth.OAuth2Config, client *http.Client, cookieCfg codersdk.HTTPCookieConfig, authURLOpts map[string]string, pkceMethods []promoauth.Oauth2PKCEChallengeMethod) func(http.Handler) http.Handler {
49 opts := make([]oauth2.AuthCodeOption, 0, len(authURLOpts)+1)
50 opts = append(opts, oauth2.AccessTypeOffline)
51 for k, v := range authURLOpts {
52 opts = append(opts, oauth2.SetAuthURLParam(k, v))
53 }
54
55 // Only S256 PKCE is currently supported.
56 sha256PKCESupported := slices.Contains(pkceMethods, promoauth.PKCEChallengeMethodSha256)
57 return func(next http.Handler) http.Handler {
58 return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
59 ctx := r.Context()
60 if client != nil {
61 ctx = context.WithValue(ctx, oauth2.HTTPClient, client)
62 }
63
64 // Interfaces can hold a nil value
65 if config == nil || reflect.ValueOf(config).IsNil() {
66 httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
67 Message: "The oauth2 method requested is not configured!",
68 })
69 return
70 }
71
72 // OIDC errors can be returned as query parameters. This can happen
73 // if for example we are providing and invalid scope.
74 // We should terminate the OIDC process if we encounter an error.
75 errorMsg := r.URL.Query().Get("error")
76 errorDescription := r.URL.Query().Get("error_description")
77 errorURI := r.URL.Query().Get("error_uri")
78 if errorMsg != "" {
79 // Combine the errors into a single string if either is provided.
80 if errorDescription == "" && errorURI != "" {
81 errorDescription = fmt.Sprintf("error_uri: %s", errorURI)
82 } else if errorDescription != "" && errorURI != "" {
83 errorDescription = fmt.Sprintf("%s, error_uri: %s", errorDescription, errorURI)
84 }
85 errorMsg = fmt.Sprintf("Encountered error in oidc process: %s", errorMsg)
86 httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
87 Message: errorMsg,
88 // This message might be blank. This is ok.
89 Detail: errorDescription,
90 })
91 return
92 }
93
94 code := r.URL.Query().Get("code")
95 state := r.URL.Query().Get("state")
96 redirect := r.URL.Query().Get("redirect")
97 if redirect != "" {
98 // We want to ensure that we're only ever redirecting to the application.
99 // We could be more strict here and check to see if the host matches
100 // the host of the AccessURL but ultimately as long as our redirect
101 // url omits a host we're ensuring that we're routing to a path
102 // local to the application.
103 redirect = uriFromURL(redirect)
104 }
105

Callers 1

TestOAuth2Function · 0.92

Calls 13

WriteFunction · 0.92
StringFunction · 0.92
WithContextMethod · 0.80
uriFromURLFunction · 0.70
ContextMethod · 0.65
GetMethod · 0.65
ApplyMethod · 0.65
AuthCodeURLMethod · 0.65
ExchangeMethod · 0.65
ContainsMethod · 0.45
ErrorMethod · 0.45
CloneMethod · 0.45

Tested by 1

TestOAuth2Function · 0.74