...

Расшифровка JWT-токена для OAuth2

Тема в разделе "Примеры сценариев", создана пользователем vyimova, 12 май 2023.

  1. vyimova

    vyimova Участник

    Данная статья – идейный сиквел статьи Пользовательский модуль OAuth2 для авторизации через Яндекс ID, поэтому перед прочтением этой статьи настоятельно рекомендую ознакомиться со статьей-приквелом, т.к. к ней в тексте будет много отсылок.

    Некоторые сервисы, с которыми мы хотим интегрироваться посредством OAuth2, не предоставляют endpoint для получения информации о пользователе. Например, в предыдущей статье про Яндекс ID таким endpoint’ом был url «https://login.yandex.ru/info». Его задача состояла в том, чтобы обменять токен доступа на информацию о пользователе и вернуть информацию в ответе на запрос в формате JSON. В данном JSON содержится список параметров, который зависит от заданных в настройках модуля scopes (права доступа).

    Однако, если у нас отсутствует такой endpoint, но есть токен доступа (access_token), мы можем расшифровать данный токен самостоятельно и получить необходимые нам параметры. Важное условие – токен доступа должен являться JWT (JSON Web Token). Токен JWT состоит из трех частей: заголовка (header), полезной нагрузки (payload) и подписи или данных шифрования. Эти три элемента разделяются точками (символ «.»).

    ! Важно, чтобы токен был именно в таком формате, с зашифрованной информацией в трех частях строки. Если токен находится в каком-либо другом формате, то его не получится расшифровать таким способом. Например, в Яндекс ID access_token выводится в виде одной строки, не разделенной точками. Такую строку расшифровать способами, указанными ниже, не получится.

    Способы расшифровки

    1. Сайт jwt.io

    Для расшифровки JWT-токенов есть сайт: https://jwt.io/. В нем можно проверять вручную, что содержится в токене доступа.

    Нас интересуют значения в блоке Payload.

    [​IMG]

    2. Сценарий в Методе API

    Однако в ELMA365 расшифровывать токен необходимо в рамках сценария метода API, который мы используем в модуле OAuth2, т.к. нам нужно в нем инициализировать и вернуть необходимые нам для авторизации параметры (user_id, email).

    Расшифровывать нам надо не токен целиком, а только полезную нагрузку (payload). Поэтому прежде всего из токена нам нужно получить «среднюю» часть, которая находится в строке с токеном между первой точкой и последней точкой. Далее воспользуемся функцией atob() для декодирования токена.

    Преобразуем код Метода API из предыдущей статьи таким образом:
    Код:
    
    interface AccessTokenData {
        
    access_tokenstring;
        
    refresh_tokenstring;
        
    token_typestring;
        
    expires_innumber;
    }

    interface 
    OAuth2Profile {
        
    // идентификатор пользователя
        
    user_idstring;
        
    // почта пользователя
        
    emailstring;
    }

    interface 
    OAuth2ResponseFail {
        
    errorstring;
        
    error_descriptionstring;
    }

    async function oauth2_profile (tokenDataAccessTokenData): Promise<OAuth2Profile OAuth2ResponseFail> {
        
    // конвертируем token в string
        
    let token_string tokenData.access_token.toString();

        
    // извлечение из строки token_string только средней части токена (находится между двух точек)
        // отбросили часть после второй точки
        
    token_string token_string.slice(0token_string.lastIndexOf("."));
        
    // отбросили часть до первой точки (header)
        
    token_string token_string.slice(token_string.indexOf(".") + 1token_string.length);

        
    // расшифровываем токен функцией atob для получения из расшифрованного токена ответ вида JSON с данными о пользователе
        
    let res atob(token_string);

        
    // конвертируем после расшифровки токена строку с ответом в формат JSON
        
    const body JSON.parse(res);

        
    // выполняем привязку OAuth2
        // sub и email – условные наименования параметров в JSON, для каждого сервиса будут свои наименования
        
    return <OAuth2Profile>{
            
    user_idbody.sub.toString(),
            
    emailbody.email.toString()
        };
    }
    Параметры модуля и прочие настройки аналогичны настройкам, описанным в предыдущей статье про OAuth2. Значения переменных модуля варьируются в зависимости от используемого сервиса.

    При корректных настройках работать модуль будет аналогично модулю, описанному в предыдущей статье. В случае успешной интеграции будет осуществляться корректная авторизация на стенде ELMA365 через сторонний сервис.