func AuthenticateToken(c *Context, fn HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { token, err := jwt.ParseFromRequest(r, func(parsedToken *jwt.Token) (interface{}, error) { if _, ok := parsedToken.Method.(*jwt.SigningMethodRSA); !ok { return nil, fmt.Errorf("Unrecognized signing method: %v", parsedToken.Header["alg"]) } else { return settings.GetPublicKey(), nil } }) if err == jwt.ErrNoTokenInRequest { fn(c, w, r) return } else if err != nil { http.Error(w, err.Error(), http.StatusUnauthorized) return } if !token.Valid { http.Error(w, "Invalid JWT", http.StatusUnauthorized) return } var ok bool c.UserID, ok = token.Claims["sub"].(string) if !ok { log.Fatal("The underlying type of sub is not string") } isStored, err := c.TokenStore.IsTokenStored(c.UserID) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if isStored { http.Error(w, "Token is no longer valid", http.StatusUnauthorized) return } _, ok = token.Claims["exp"].(float64) if !ok { log.Fatal("The underlying type of exp is not float64") } fn(c, w, r) } }
func TestLoginWithCorrectPassword(t *testing.T) { ac := &AuthContext{UserID: "0"} retrievedToken, err := ac.Login("password", "$2a$10$F4B95tmhW6VfQ.l.mhUj6Ow3Eg5dViTiJDsFzh8VaQr9Urd70LP9W") if err != nil { t.Error(err) } parsedToken, err := jwt.Parse(retrievedToken.SignedToken, func(token *jwt.Token) (interface{}, error) { return settings.GetPublicKey(), nil }) if err != nil { t.Error(err) } parsedTokenUserID, ok := parsedToken.Claims["sub"].(string) if !ok { t.Errorf("The parsedToken \"sub\" claim does not have an underlying type of string") } if parsedTokenUserID != ac.UserID { t.Errorf("Expected to retrieve a token with a \"sub\" claim of %s, but the retrieved token has a \"sub\" claim of %s", ac.UserID, parsedTokenUserID) } }