Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/add issuer into jwt claims #311

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -152,6 +152,10 @@ How long tokens are valid for, in seconds. Defaults to 3600 (1 hour).

The default JWT audience. Use audiences to group users.

`JWT_ISS` - `string`

The "iss" (issuer) claim identifies the principal that issued the JWT

`JWT_ADMIN_GROUP_NAME` - `string`

The name of the admin group (if enabled). Defaults to `admin`.
Expand Down
4 changes: 2 additions & 2 deletions api/admin_test.go
Expand Up @@ -55,7 +55,7 @@ func (ts *AdminTestSuite) makeSuperAdmin(email string) string {
u.IsSuperAdmin = true
require.NoError(ts.T(), ts.API.db.Create(u), "Error creating user")

token, err := generateAccessToken(u, time.Second*time.Duration(ts.Config.JWT.Exp), ts.Config.JWT.Secret)
token, err := generateAccessToken(u, time.Second*time.Duration(ts.Config.JWT.Exp), ts.Config.JWT.Secret, ts.Config.JWT.Iss)
require.NoError(ts.T(), err, "Error generating access token")

p := jwt.Parser{ValidMethods: []string{jwt.SigningMethodHS256.Name}}
Expand All @@ -70,7 +70,7 @@ func (ts *AdminTestSuite) makeSuperAdmin(email string) string {
func (ts *AdminTestSuite) makeSystemUser() string {
u := models.NewSystemUser(uuid.Nil, ts.Config.JWT.Aud)

token, err := generateAccessToken(u, time.Second*time.Duration(ts.Config.JWT.Exp), ts.Config.JWT.Secret)
token, err := generateAccessToken(u, time.Second*time.Duration(ts.Config.JWT.Exp), ts.Config.JWT.Secret, ts.Config.JWT.Iss)
require.NoError(ts.T(), err, "Error generating access token")

p := jwt.Parser{ValidMethods: []string{jwt.SigningMethodHS256.Name}}
Expand Down
2 changes: 1 addition & 1 deletion api/audit_test.go
Expand Up @@ -52,7 +52,7 @@ func (ts *AuditTestSuite) makeSuperAdmin(email string) string {
u.IsSuperAdmin = true
require.NoError(ts.T(), ts.API.db.Create(u), "Error creating user")

token, err := generateAccessToken(u, time.Second*time.Duration(ts.Config.JWT.Exp), ts.Config.JWT.Secret)
token, err := generateAccessToken(u, time.Second*time.Duration(ts.Config.JWT.Exp), ts.Config.JWT.Secret, ts.Config.JWT.Iss)
require.NoError(ts.T(), err, "Error generating access token")

p := jwt.Parser{ValidMethods: []string{jwt.SigningMethodHS256.Name}}
Expand Down
2 changes: 1 addition & 1 deletion api/invite_test.go
Expand Up @@ -61,7 +61,7 @@ func (ts *InviteTestSuite) makeSuperAdmin(email string) string {
u.IsSuperAdmin = true
require.NoError(ts.T(), ts.API.db.Create(u), "Error creating user")

token, err := generateAccessToken(u, time.Second*time.Duration(ts.Config.JWT.Exp), ts.Config.JWT.Secret)
token, err := generateAccessToken(u, time.Second*time.Duration(ts.Config.JWT.Exp), ts.Config.JWT.Secret, ts.Config.JWT.Iss)
require.NoError(ts.T(), err, "Error generating access token")

p := jwt.Parser{ValidMethods: []string{jwt.SigningMethodHS256.Name}}
Expand Down
7 changes: 4 additions & 3 deletions api/token.go
Expand Up @@ -139,7 +139,7 @@ func (a *API) RefreshTokenGrant(ctx context.Context, w http.ResponseWriter, r *h
return internalServerError(terr.Error())
}

tokenString, terr = generateAccessToken(user, time.Second*time.Duration(config.JWT.Exp), config.JWT.Secret)
tokenString, terr = generateAccessToken(user, time.Second*time.Duration(config.JWT.Exp), config.JWT.Secret, config.JWT.Iss)
if terr != nil {
return internalServerError("error generating jwt token").WithInternalError(terr)
}
Expand All @@ -163,12 +163,13 @@ func (a *API) RefreshTokenGrant(ctx context.Context, w http.ResponseWriter, r *h
})
}

func generateAccessToken(user *models.User, expiresIn time.Duration, secret string) (string, error) {
func generateAccessToken(user *models.User, expiresIn time.Duration, secret string, iss string) (string, error) {
claims := &GoTrueClaims{
StandardClaims: jwt.StandardClaims{
Subject: user.ID.String(),
Audience: user.Aud,
ExpiresAt: time.Now().Add(expiresIn).Unix(),
Issuer: Iss,
},
Email: user.Email,
AppMetaData: user.AppMetaData,
Expand All @@ -195,7 +196,7 @@ func (a *API) issueRefreshToken(ctx context.Context, conn *storage.Connection, u
return internalServerError("Database error granting user").WithInternalError(terr)
}

tokenString, terr = generateAccessToken(user, time.Second*time.Duration(config.JWT.Exp), config.JWT.Secret)
tokenString, terr = generateAccessToken(user, time.Second*time.Duration(config.JWT.Exp), config.JWT.Secret, config.JWT.Iss)
if terr != nil {
return internalServerError("error generating jwt token").WithInternalError(terr)
}
Expand Down
2 changes: 1 addition & 1 deletion api/user_test.go
Expand Up @@ -62,7 +62,7 @@ func (ts *UserTestSuite) TestUser_UpdatePassword() {
req := httptest.NewRequest(http.MethodPut, "http://localhost/user", &buffer)
req.Header.Set("Content-Type", "application/json")

token, err := generateAccessToken(u, time.Second*time.Duration(ts.Config.JWT.Exp), ts.Config.JWT.Secret)
token, err := generateAccessToken(u, time.Second*time.Duration(ts.Config.JWT.Exp), ts.Config.JWT.Secret, ts.Config.JWT.Iss)
require.NoError(ts.T(), err)
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))

Expand Down
1 change: 1 addition & 0 deletions conf/configuration.go
Expand Up @@ -44,6 +44,7 @@ type DBConfiguration struct {
// JWTConfiguration holds all the JWT related configuration.
type JWTConfiguration struct {
Secret string `json:"secret" required:"true"`
Iss string `json:"iss"`
Exp int `json:"exp"`
Aud string `json:"aud"`
AdminGroupName string `json:"admin_group_name" split_words:"true"`
Expand Down
1 change: 1 addition & 0 deletions example.env
@@ -1,6 +1,7 @@
GOTRUE_JWT_SECRET="CHANGE-THIS! VERY IMPORTANT!"
GOTRUE_JWT_EXP=3600
GOTRUE_JWT_AUD=api.netlify.com
GOTRUE_JWT_ISS=api.netlify.com
GOTRUE_DB_DRIVER=mysql
DATABASE_URL="root@tcp(127.0.0.1:3306)/gotrue_development?parseTime=true&multiStatements=true"
GOTRUE_API_HOST=localhost
Expand Down
1 change: 1 addition & 0 deletions hack/test.env
@@ -1,6 +1,7 @@
GOTRUE_JWT_SECRET=testsecret
GOTRUE_JWT_EXP=3600
GOTRUE_JWT_AUD=api.netlify.com
GOTRUE_JWT_ISS=api.netlify.com
GOTRUE_DB_DRIVER=mysql
GOTRUE_DB_AUTOMIGRATE=true
GOTRUE_DB_NAMESPACE=test
Expand Down