go-twitch/auth/authorize.go

96 lines
3.1 KiB
Go
Raw Permalink Normal View History

2024-03-04 18:14:38 -05:00
package auth
import (
"net/http"
"net/url"
"github.com/google/go-querystring/query"
)
type AuthorizeParams struct {
// A string-encoded JSON object that specifies the claims to include in the ID token.
// For information about claims, see Requesting claims: https://dev.twitch.tv/docs/authentication/getting-tokens-oidc/#requesting-claims
//
// Only used for OIDC auth flows
Claims *Claims `url:"claims"`
// Set to true to force the user to re-authorize your apps access to their resources.
// The default is false.
ForceVerify *bool `url:"force_verify"`
// Although optional, you are strongly encouraged to pass a nonce string to help
// prevent Cross-Site Request Forgery (CSRF) attacks. The server returns this string
// to you in the ID tokens list of claims. If this string doesnt match the nonce
// string that you passed, ignore the response. The nonce string should be randomly
// generated and unique for each OAuth request.
//
// Only used for OIDC auth flows
Nonce *string `url:"nonce"`
// Must be set to code for Authorization code grant flow.
// Recommended for Server-to-Server flows. (with backend)
//
// Must be set to token for Implicit grant flow.
// Recommended for Client-to-Server flows. (no backend)
ResponseType string `url:"response_type"`
// A space-delimited list of scopes. The APIs that youre calling identify the
// scopes you must list. The list must include the openid scope. Dont forget to
// URL encode the list.
Scope []Scope `url:"scope,space"`
// Although optional, you are strongly encouraged to pass a state string to help
// prevent Cross-Site Request Forgery (CSRF) attacks. The server returns this string
// to you in your redirect URI (see the state parameter in the fragment portion of
// the URI). If this string doesnt match the state string that you passed, ignore
// the response. The state string should be randomly generated and unique for each
// OAuth request.
State *string `url:"state"`
}
const AuthorizeUrl = "https://id.twitch.tv/oauth2/authorize"
// AuthorizeUrl returns the URL to redirect the user to for authorization.
func (c *Client) AuthorizeUrl(params *AuthorizeParams) *url.URL {
v, _ := query.Values(params)
v.Set("client_id", c.clientId)
v.Set("redirect_uri", c.redirectUri)
url, _ := url.Parse(AuthorizeUrl)
url.RawQuery = v.Encode()
return url
}
type AuthorizeHandler struct {
client *Client
scopes []Scope
}
var _ http.Handler = (*AuthorizeHandler)(nil)
// AuthorizeHandler returns an http.Handler that redirects the user to the
// authorization URL.
func (c *Client) AuthorizeHandler(scopes []Scope) http.Handler {
return &AuthorizeHandler{
client: c,
scopes: scopes,
}
}
// ServeHTTP implements http.Handler.
func (h *AuthorizeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
state := GenerateState()
if err := h.client.stateStorage.Save(w, state); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
url := h.client.AuthorizeUrl(&AuthorizeParams{
ResponseType: "code",
Scope: h.scopes,
State: &state,
})
http.Redirect(w, r, url.String(), http.StatusFound)
}