Где проверяется секретный ключ JWT при разборе токена jwt?

Я читаю папку с примерами для JWT, я немного не уверен, как работает проверка токена.

func ExampleNewWithClaims_customClaimsType() {
    mySigningKey := []byte("AllYourBase")

    type MyCustomClaims struct {
        Foo string `json:"foo"`
        jwt.StandardClaims
    }

    // Create the Claims
    claims := MyCustomClaims{
        "bar",
        jwt.StandardClaims{
            ExpiresAt: 15000,
            Issuer:    "test",
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    ss, err := token.SignedString(mySigningKey)
    fmt.Printf("%v %v", ss, err)
    //Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c <nil>
}

Здесь все просто, и токен подписывается здесь token.SignedString(mySigningKey) с помощью "mySigningKey"

Теперь разбор для меня гораздо менее понятен:

func ExampleParseWithClaims_customClaimsType() {
    tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"

    type MyCustomClaims struct {
        Foo string `json:"foo"`
        jwt.StandardClaims
    }

    // sample token is expired.  override time so it parses as valid
    at(time.Unix(0, 0), func() {
        token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
            return []byte("AllYourBase"), nil
        })

        if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid {
            fmt.Printf("%v %v", claims.Foo, claims.StandardClaims.ExpiresAt)
        } else {
            fmt.Println(err)
        }
    })

    // Output: bar 15000
}

Это порядок проверки того, что подпись строки токена, возвращенной клиентом, действительна, нужно ли вам

  • расшифровать заявку (выполняется в & MyCustomClaims {})
  • проверить, что подпись декодированного утверждения действительна для «ключа публикации, включенного в токен», с помощью token.Valid.

Но в этом примере просто расшифровывается ключ и "magic" возвращается секретный ключ / ключ подписи?

Для меня это вообще не имеет смысла. Также бесполезно возвращать действительное заявление об открытом ключе, поскольку это могло быть сделано с помощью любого закрытого ключа.

Что мне не хватает?


person user7952151    schedule 26.05.2020    source источник
comment
Функция, переданная в качестве последнего аргумента ParseWithClaims, возвращает ключ. Ключ не является частью токена (вы правы, это сделало бы токен совершенно бессмысленным).   -  person Peter    schedule 26.05.2020


Ответы (1)


Проверка не выполняется открытым ключом, включенным в токен.

HS256 является симметричным, поэтому какой бы ключ вы ни использовали для подписи токена, вы должны использовать тот же ключ для проверки подписи, и вот что происходит. Функция, переданная в ParseWithClaims, возвращает тот же ключ, который использовался для подписи токена.

Если использовался алгоритм асимметричной подписи, вы использовали бы закрытый ключ для подписи токена, а затем открытый ключ для его проверки, и эта вложенная функция должна была бы вернуть открытый ключ, чтобы ParseWithClaims мог его проверить.

Похоже, что вас смутило следующее:

jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
            return []byte("AllYourBase"), nil
        })

Вложенная функция, переданная в ParseWithClaims, должна проверять переданный токен и возвращать правильный ключ, который можно использовать для проверки подписи. Для HS256 это тот же ключ, который использовался для его подписи. Для RSxxx это будет открытый ключ, и какой открытый ключ он должен вернуть, можно получить из переданного токена. Обычно он содержит идентификатор открытого ключа, поэтому вы можете выбрать правильный ключ.

person Burak Serdar    schedule 26.05.2020
comment
Я чувствую себя идиотом, но не понимаю этой роли. в первом примере есть явный mySigningKey := []byte("AllYourBase"), но во второй функции я не понимаю, как функция синтаксического анализа с параметром строки токена (которая должна быть общедоступной, отправленной пользователем) может вернуть ключ. Почему мой секретный ключ / ключ подписи никогда не вводился для его проверки (подпись) - person user7952151; 26.05.2020
comment
Вы говорите, что должны использовать один и тот же ключ для проверки подписи, и это имеет смысл. но я не вижу, где я даю ключ. - person user7952151; 26.05.2020
comment
Ой, плохо. Я понял. Я фактически передаю функцию с моим ключом, включенным в качестве параметра с проверкой действительности, это не возврат из функции синтаксического анализа, а параметр! Спасибо! - person user7952151; 26.05.2020