// StateHandler checks for a state cookie. If found, the state value is read // and added to the ctx. Otherwise, a non-guessable value is added to the ctx // and to a (short-lived) state cookie issued to the requester. // // Implements OAuth 2 RFC 6749 10.12 CSRF Protection. If you wish to issue // state params differently, write a ContextHandler which sets the ctx state, // using oauth2 WithState(ctx, state) since it is required by LoginHandler // and CallbackHandler. func StateHandler(config gologin.CookieConfig, success ctxh.ContextHandler) ctxh.ContextHandler { fn := func(ctx context.Context, w http.ResponseWriter, req *http.Request) { cookie, err := req.Cookie(config.Name) if err == nil { // add the cookie state to the ctx ctx = WithState(ctx, cookie.Value) } else { // add Cookie with a random state val := randomState() http.SetCookie(w, internal.NewCookie(config, val)) ctx = WithState(ctx, val) } success.ServeHTTP(ctx, w, req) } return ctxh.ContextHandlerFunc(fn) }
// CookieTempHandler persists or retrieves the request token secret (temporary // credentials). If the request token can be read from the ctx (login phase), // the secret is set in a short-lived cookie to be read later. Otherwise // (callback phase) the cookie is read to retrieve the request token secret // and add it to the ctx. // If the ctx contains no request token and the request has no temp cookie, // the failure handler is called. // // Some OAuth1 providers (Twitter, Digits) do NOT require temp secrets to be // kept between the login phase and callback phase. To implement those // providers, use the EmptyTempHandler instead. func CookieTempHandler(config gologin.CookieConfig, success, failure ctxh.ContextHandler) ctxh.ContextHandler { if failure == nil { failure = gologin.DefaultFailureHandler } fn := func(ctx context.Context, w http.ResponseWriter, req *http.Request) { _, requestSecret, err := RequestTokenFromContext(ctx) if err == nil { // add request secret to a short-lived cookie http.SetCookie(w, internal.NewCookie(config, requestSecret)) success.ServeHTTP(ctx, w, req) return } // read request secret from the short-lived cookie to add to ctx cookie, err := req.Cookie(config.Name) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } ctx = WithRequestToken(ctx, "", cookie.Value) success.ServeHTTP(ctx, w, req) } return ctxh.ContextHandlerFunc(fn) }