Идентификация пользователя с использованием аутентификации токена jwt

0

Я использую jersey rest webservice вместе с JWT с маркером маркера RSA для аутентификации. Я смог успешно создать и отправить токен в интерфейс. Теперь, когда я достиг этого, я смущен проверкой токена, а также идентификацией пользователя, запрашивающего ресурсы.

Несколько вопросов здесь:

  1. Должен ли я декодировать токен jwt, полученный на интерфейсе, чтобы проверить претензии?
  2. Как определить пользователя, запрашивающего ресурс на сервере?

Поскольку на некоторых из сообщений на SO некоторые люди заявили, что не требуется декодировать токен на лицевой стороне (проверьте эту ссылку), в то время как другие примеры на других сайтах показывают пример декодирования маркера на лицевой стороне, такой как этот

Теперь я смущен, как идти дальше о том, должен ли я фактически декодировать токен на интерфейсе или оставить его как есть? Если да, то как другие примеры показывают декодирование на интерфейсе следующим образом:

angular.module('app')
   .factory('Auth', ['$http', '$localStorage', 'urls', function ($http, $localStorage, urls) {
       function urlBase64Decode(str) {
           var output = str.replace('-', '+').replace('_', '/');
           switch (output.length % 4) {
               case 0:
                   break;
               case 2:
                   output += '==';
                   break;
               case 3:
                   output += '=';
                   break;
               default:
                   throw 'Illegal base64url string!';
           }
           return window.atob(output);
       }

       function getClaimsFromToken() {
           var token = $localStorage.token;
           var user = {};
           if (typeof token !== 'undefined') {
               var encoded = token.split('.')[1];
               user = JSON.parse(urlBase64Decode(encoded));
           }
           return user;
       }

Пример токена, который я использую здесь:

private void authenticate(String email, String password)
    throws Exception {
try {
    Connection con = DBConnection.getConnection();
    PreparedStatement statement = con.prepareStatement("select USR_PRIMARY_EMAIL, USR_PASSWORD from TBL_USER where USR_PRIMARY_EMAIL=? and USR_PASSWORD=?");
    statement.setString(1, email);
    statement.setString(2, password);
    ResultSet result = statement.executeQuery();
    if (result.next()) {
        System.out.println("User authenticated successfully");

        KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("RSA");
        keyGenerator.initialize(1024);

        KeyPair kp = keyGenerator.genKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate();
        JWSSigner signer = new RSASSASigner(privateKey);

        JWTClaimsSet claimsSet = new JWTClaimsSet();
        claimsSet.setSubject("alice");
        claimsSet.setIssuer("https://c2id.com");
        claimsSet.setExpirationTime(new Date(new Date().getTime() + 60 * 1000));

        System.out.println("publicKey is: " + publicKey);
        System.out.println("privateKey is: " + privateKey);
        System.out.println("claimsSet is: " + claimsSet);

        SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256),claimsSet);

        signedJWT.sign(signer);
        token = signedJWT.serialize();
        System.out.println("Token is: " + token);

        signedJWT = SignedJWT.parse(token);

        System.out.println("signedJWT is: " + signedJWT);

        JWSVerifier verifier = new RSASSAVerifier(publicKey);
        assertTrue(signedJWT.verify(verifier));
        assertEquals("alice", signedJWT.getJWTClaimsSet().getSubject());
        assertEquals("https://c2id.com", signedJWT.getJWTClaimsSet().getIssuer());
        assertTrue(new Date().before(signedJWT.getJWTClaimsSet().getExpirationTime()));
    } else {
        System.out.println("User doesn't exist");
    }
} catch (Exception e) {
    System.out.println("DB related Error");
    e.printStackTrace();
}
}

Еще одна проблема - это токен, созданный с помощью nimbus + jose_JWT (RSA-подпись). Я не могу декодировать в угловой библиотеке auth0. Это потому, что я использую открытый ключ?

Теги:
jwt
jersey
jose4j

1 ответ

3

Должен ли я декодировать токен jwt, полученный на интерфейсе, чтобы проверить претензии?

Да. Набор утверждений JWT - это JSON с кодировкой base64URL, поэтому вам нужно декодировать его, чтобы прочитать его.


Как определить пользователя, запрашивающего ресурс на сервере?

sub требование не является обязательным, но практически каждый провайдер JWT будет выдавать все маркера с предметом ID, который идентифицирует запрашивающий. Из спецификации JWT:

Заявка "под" (субъект) идентифицирует принципала, который является субъектом JWT. Претензии в JWT обычно являются заявлениями о предмете. Значение предмета ДОЛЖНО либо быть локальным, либо локально уникальным в контексте эмитента, либо быть глобально уникальным. Обработка этой заявки, как правило, зависит от конкретного приложения. Значение "sub" является строкой, чувствительной к регистру, содержащей значение StringOrURI. Использование этого требования ДОПОЛНИТЕЛЬНО.


Еще одна проблема - это токен, созданный с помощью nimbus + jose_JWT (RSA-подпись). Я не могу декодировать в угловой библиотеке auth0. Это потому, что я использую открытый ключ?

Нет. Все наборы требований JWT являются JSON с кодировкой base64URL независимо от метода подписи, поэтому вы должны иметь возможность декодировать его.

  • 0
    Привет Родриго. Большое спасибо за ваш ответ. Теперь я могу правильно декодировать токен, но дело в том, что он возвращает только полезную информацию, такую как sub , iss и exp но без заголовка и подписи? Нужны ли мне эти значения, чтобы идентифицировать пользователя? а также вставить информацию авторизации в заголовок? или достаточно только полезной информации?
  • 0
    При вызове API, который принимает JWT, вы просто передаете весь JWT в заголовке Authorization (например, Authorization: Bearer eyJ... ). Библиотеки JWT позволят вам получить доступ к набору утверждений при декодировании токена. Доступ к заголовку обычно не требуется, поскольку вы должны заранее знать, какой алгоритм подписи вы ожидаете (см. Auth0.com/blog/2015/03/31/… ). Также нет необходимости обращаться к подписи вручную, так как вы должны использовать методы проверки библиотеки напрямую.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню