forked from vikunja/vikunja
131 lines
3.9 KiB
Go
131 lines
3.9 KiB
Go
// Vikunja is a to-do list application to facilitate your life.
|
|
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package identityawareproxy
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/dgrijalva/jwt-go"
|
|
"github.com/lestrrat-go/jwx/jwk"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
/* Valid token with kid "sig-1606406403" and the following claims:
|
|
{
|
|
"aud": "vikunja-url",
|
|
"email": "test@example.com",
|
|
"exp": 1000,
|
|
"iat": 1,
|
|
"iss": "proxy-url",
|
|
"sub": "12345",
|
|
"user": "12345"
|
|
}*/
|
|
var validToken = "eyJhbGciOiJFUzI1NiIsImtpZCI6InNpZy0xNjA2NDA2NDAzIiwidHlwIjoiSldUIn0.eyJhdWQiOiJ2aWt1bmphLXVybCIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImV4cCI6MTAwMCwiaWF0IjoxLCJpc3MiOiJwcm94eS11cmwiLCJzdWIiOiIxMjM0NSIsInVzZXIiOiIxMjM0NSJ9.Shh0wxVaojGV2U2FQpgWgMjvU8QbjQSZcN062Qd-WShyyPG_vZsJwbBV6EVM5v_HdN2uMJN0HtEELEPBEM7Hiw"
|
|
|
|
var validJwks = `{"keys":[{
|
|
"crv":"P-256",
|
|
"kty":"EC",
|
|
"use":"sig",
|
|
"kid": "sig-1606406403",
|
|
"x":"vejjjK-FfBOLU_Vz0t12dx1zmfdR2GseEnverHOKJKk",
|
|
"y":"09pkYKAr51w8-k5s37_M9oBDU8nI4ALkLufTEumO-r4",
|
|
"alg": "ES256"
|
|
}]}`
|
|
|
|
// Override time value for tests. Restore default value after.
|
|
func at(t time.Time, f func()) {
|
|
TimeFunc = func() time.Time {
|
|
return t
|
|
}
|
|
f()
|
|
TimeFunc = time.Now
|
|
}
|
|
|
|
func TestParseAndValidateJwt(t *testing.T) {
|
|
// Run the test at a valid time for the JWT expiration
|
|
at(time.Unix(50, 0), func() {
|
|
t.Run("valid jwt and key within expiration", func(t *testing.T) {
|
|
validKeySet, _ := jwk.ParseString(validJwks)
|
|
cl, err := parseAndValidateJwt(validToken, validKeySet)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, &IAPClaims{
|
|
Email: "test@example.com",
|
|
Name: "",
|
|
PreferredUsername: "",
|
|
StandardClaims: jwt.StandardClaims{
|
|
Audience: "vikunja-url",
|
|
ExpiresAt: 1000,
|
|
Id: "",
|
|
IssuedAt: 1,
|
|
Issuer: "proxy-url",
|
|
NotBefore: 0,
|
|
Subject: "12345",
|
|
},
|
|
}, cl)
|
|
})
|
|
})
|
|
|
|
// Run the test within the skew of the the expiration
|
|
at(time.Unix(1059, 0), func() {
|
|
t.Run("valid jwt and key past expiration within skew", func(t *testing.T) {
|
|
validKeySet, _ := jwk.ParseString(validJwks)
|
|
cl, err := parseAndValidateJwt(validToken, validKeySet)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, &IAPClaims{
|
|
Email: "test@example.com",
|
|
Name: "",
|
|
PreferredUsername: "",
|
|
StandardClaims: jwt.StandardClaims{
|
|
Audience: "vikunja-url",
|
|
ExpiresAt: 1000,
|
|
Id: "",
|
|
IssuedAt: 1,
|
|
Issuer: "proxy-url",
|
|
NotBefore: 0,
|
|
Subject: "12345",
|
|
},
|
|
}, cl)
|
|
})
|
|
})
|
|
|
|
// Run the test outside the skew of the the expiration
|
|
at(time.Unix(1061, 0), func() {
|
|
t.Run("expired jwt", func(t *testing.T) {
|
|
validKeySet, _ := jwk.ParseString(validJwks)
|
|
cl, err := parseAndValidateJwt(validToken, validKeySet)
|
|
assert.Nil(t, cl)
|
|
assert.EqualError(t, err, "token is expired by 1m1s")
|
|
})
|
|
})
|
|
|
|
t.Run("missing key", func(t *testing.T) {
|
|
keySet, _ := jwk.ParseString(`{"keys":[{
|
|
"crv":"P-256",
|
|
"kty":"EC",
|
|
"use":"sig",
|
|
"kid": "non-matching-sig",
|
|
"x":"vejjjK-FfBOLU_Vz0t12dx1zmfdR2GseEnverHOKJKk",
|
|
"y":"09pkYKAr51w8-k5s37_M9oBDU8nI4ALkLufTEumO-r4",
|
|
"alg": "ES256"
|
|
}]}`)
|
|
cl, err := parseAndValidateJwt(validToken, keySet)
|
|
assert.EqualError(t, err, "JWT missing KID")
|
|
assert.Nil(t, cl)
|
|
})
|
|
}
|