OAuth2 access-code (Google)
Mirrors
go-swagger/examples/oauth2.
Most of this example is OAuth2-flow plumbing (redirect, callback,
token exchange) that lives in your code, not in the runtime — the
runtime only enters the picture for the protected endpoints, where
the bearer token is validated.
The bearer-jwt example is the right starting point if all you need is validating an inbound bearer; come here when you also want to issue the redirect dance.
Spec
Application configuration
You’ll need a registered OAuth2 client at https://console.cloud.google.com/apis/credentials/ and an exact-match callback URL.
Wiring
api := untyped.NewAPI(doc).WithJSONDefaults()
// 1. The protected-route validator. Called for any operation whose
// `security:` block lists `OauthSecurity`.
api.RegisterAuth("OauthSecurity", security.BearerAuth("OauthSecurity",
func(token string, _ []string) (any, error) {
ok, err := validateAtUserInfoURL(token)
if err != nil || !ok {
return nil, errors.Unauthenticated("bearer")
}
return token, nil
},
))
// 2. /login redirects the browser to Google's auth endpoint.
api.RegisterOperation("get", "/login", runtime.OperationHandlerFunc(
func(_ any) (any, error) {
return middleware.ResponderFunc(func(w http.ResponseWriter, _ runtime.Producer) {
// params.HTTPRequest is unused here — pass nil since middleware.Redirect ignores it
http.Redirect(w, currentRequest, config.AuthCodeURL(state), http.StatusFound)
}), nil
},
))
// 3. /auth/callback exchanges the code Google returns for an access token.
api.RegisterOperation("get", "/auth/callback", runtime.OperationHandlerFunc(
func(params any) (any, error) {
// The bound params struct exposes the raw HTTP request through HTTPRequest.
// Untyped: extract from params; typed: it's already a field.
r := params.(getCallbackParams).HTTPRequest
if r.URL.Query().Get("state") != state {
return nil, errors.New(http.StatusBadRequest, "state mismatch")
}
token, err := config.Exchange(r.Context(), r.URL.Query().Get("code"))
if err != nil {
return nil, errors.New(http.StatusInternalServerError, "token exchange failed")
}
return map[string]string{"access_token": token.AccessToken}, nil
},
))Full source: docs/examples/auth/oauth2/main.go
validateAtUserInfoURL is a plain HTTP call to Google’s userinfo
endpoint with the bearer token — see the
full implementation
in the sibling repo.
State parameter, briefly: the example uses a global string for brevity. In production this MUST be a per-session unguessable value, stored alongside the user’s session and validated on the callback — otherwise CSRF on the redirect.
Exercise
Run the full example
The complete runnable program — including the userinfo validator,
the redirect/callback handlers wired through middleware, and the
client-secret bootstrap — lives at
go-swagger/examples/oauth2.
Clone it, drop your Google client ID/secret into
restapi/implementation.go, and run.