This repository has been archived by the owner on May 2, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement request authentication with auth0
- Loading branch information
Showing
10 changed files
with
220 additions
and
147 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package authentication | ||
|
||
import ( | ||
"encoding/base64" | ||
"errors" | ||
"github.com/cyakimov/helios/authentication/providers" | ||
log "github.com/sirupsen/logrus" | ||
"net/http" | ||
"time" | ||
) | ||
|
||
const CookieName = "Helios_Authorization" | ||
const HeaderName = "Helios-Jwt-Assertion" | ||
|
||
var ErrUnauthorized = errors.New("unauthorized request") | ||
|
||
type JWTOpts struct { | ||
Secret string | ||
Expiration time.Duration | ||
} | ||
|
||
type Helios struct { | ||
provider providers.OAuth2 | ||
jwtOpts JWTOpts | ||
} | ||
|
||
func NewHeliosAuthentication(provider providers.OAuth2, jwtSecret string, jwtExpiration time.Duration) Helios { | ||
return Helios{ | ||
provider: provider, | ||
jwtOpts: JWTOpts{ | ||
Secret: jwtSecret, | ||
Expiration: jwtExpiration, | ||
}, | ||
} | ||
} | ||
|
||
func (helios Helios) Middleware(next http.Handler) http.Handler { | ||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
if err := authenticate(helios.jwtOpts.Secret, r); err != nil { | ||
|
||
// dynamically build callback URL based on current domain | ||
callback := "https://" + r.Host + "/.oauth2/callback" | ||
|
||
url := helios.provider.GetLoginURL(callback, r.RequestURI) | ||
|
||
log.Debugf("Redirecting to %s", url) | ||
|
||
http.Redirect(w, r, url, http.StatusTemporaryRedirect) | ||
return | ||
} | ||
|
||
log.Println(r.RequestURI) | ||
// Call the next handler, which can be another middleware in the chain, or the final handler. | ||
next.ServeHTTP(w, r) | ||
}) | ||
} | ||
|
||
func (helios Helios) CallbackHandler(w http.ResponseWriter, r *http.Request) { | ||
// decode and decrypt state to recover original request url | ||
encodedState := r.URL.Query().Get("state") | ||
|
||
state, err := base64.StdEncoding.DecodeString(encodedState) | ||
if err != nil { | ||
log.Error(err) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
profile, err := helios.provider.GetUserProfile(r) | ||
if err != nil { | ||
log.Error(err) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
log.Debugf("Authorized. Redirecting to %s", string(state)) | ||
|
||
exp := time.Now().Add(helios.jwtOpts.Expiration) | ||
jwt, err := IssueJWTWithSecret(helios.jwtOpts.Secret, profile.Email, exp) | ||
http.SetCookie(w, &http.Cookie{ | ||
Name: CookieName, | ||
Value: jwt, | ||
Expires: exp, | ||
Path: "/", | ||
Secure: true, | ||
}) | ||
|
||
http.Redirect(w, r, string(state), http.StatusFound) | ||
return | ||
} | ||
|
||
func authenticate(jwtSecret string, r *http.Request) error { | ||
// look for Token in both Cookies and Headers | ||
cookie, err := r.Cookie(CookieName) | ||
token := r.Header.Get(HeaderName) | ||
|
||
if err == http.ErrNoCookie && token == "" { | ||
return ErrUnauthorized | ||
} | ||
|
||
if token == "" { | ||
token = cookie.Value | ||
} | ||
|
||
if !ValidateJWTWithSecret(jwtSecret, token) { | ||
return ErrUnauthorized | ||
} | ||
|
||
return nil | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package providers | ||
|
||
import ( | ||
"errors" | ||
"net/http" | ||
) | ||
|
||
type OAuth2Config struct { | ||
ClientID string | ||
ClientSecret string | ||
AuthURL string | ||
TokenURL string | ||
ProfileURL string | ||
} | ||
|
||
type OIDCProfile struct { | ||
Email string | ||
} | ||
|
||
type OAuth2 interface { | ||
GetUserProfile(r *http.Request) (OIDCProfile, error) | ||
GetLoginURL(callbackURL, state string) string | ||
} | ||
|
||
var ErrCodeExchange = errors.New("error on code exchange") | ||
var ErrProfile = errors.New("error getting user profile") | ||
var ErrNoEmail = errors.New("no email found in user profile") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.