Basic but complete authentication flow
This commit is contained in:
56
internal/token/generate.go
Normal file
56
internal/token/generate.go
Normal file
@ -0,0 +1,56 @@
|
||||
package token
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
||||
const (
|
||||
jwtIssuer = "hydra-passwordless"
|
||||
)
|
||||
|
||||
type privateClaims struct {
|
||||
Challenge string `json:"challenge"`
|
||||
}
|
||||
|
||||
func Generate(signingKey, encryptionKey, email, challenge string) (string, error) {
|
||||
sig, err := jose.NewSigner(
|
||||
jose.SigningKey{
|
||||
Algorithm: jose.HS256,
|
||||
Key: []byte(signingKey),
|
||||
},
|
||||
(&jose.SignerOptions{}).WithType("JWT"),
|
||||
)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "could not create jwt signer")
|
||||
}
|
||||
|
||||
enc, err := jose.NewEncrypter(
|
||||
jose.A256GCM,
|
||||
jose.Recipient{
|
||||
Algorithm: jose.DIRECT,
|
||||
Key: []byte(encryptionKey),
|
||||
},
|
||||
(&jose.EncrypterOptions{}).WithType("JWT").WithContentType("JWT"))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "could not create jwt encrypter")
|
||||
}
|
||||
|
||||
claims := jwt.Claims{
|
||||
Subject: email,
|
||||
Issuer: jwtIssuer,
|
||||
Audience: jwt.Audience{jwtIssuer},
|
||||
}
|
||||
|
||||
privateClaims := privateClaims{
|
||||
Challenge: challenge,
|
||||
}
|
||||
|
||||
raw, err := jwt.SignedAndEncrypted(sig, enc).Claims(claims).Claims(privateClaims).CompactSerialize()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "could not sign and encrypt jwt")
|
||||
}
|
||||
|
||||
return raw, nil
|
||||
}
|
27
internal/token/verify.go
Normal file
27
internal/token/verify.go
Normal file
@ -0,0 +1,27 @@
|
||||
package token
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
||||
func Verify(signingKey, encryptionKey, raw string) (string, string, error) {
|
||||
token, err := jwt.ParseSignedAndEncrypted(raw)
|
||||
if err != nil {
|
||||
return "", "", errors.Wrap(err, "could not parse token")
|
||||
}
|
||||
|
||||
nested, err := token.Decrypt([]byte(encryptionKey))
|
||||
if err != nil {
|
||||
return "", "", errors.Wrap(err, "could not decrypt token")
|
||||
}
|
||||
|
||||
baseClaims := jwt.Claims{}
|
||||
privateClaims := privateClaims{}
|
||||
|
||||
if err := nested.Claims([]byte(signingKey), &baseClaims, &privateClaims); err != nil {
|
||||
return "", "", errors.Wrap(err, "could not validate claims")
|
||||
}
|
||||
|
||||
return baseClaims.Subject, privateClaims.Challenge, nil
|
||||
}
|
Reference in New Issue
Block a user