Slim4 + JWT
1) Registered claims 규칙
https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-token-claims
The JWT specification defines seven reserved claims that are not required, but are recommended to allow interoperability with third-party applications. These are:
iss
(issuer): Issuer of the JWT //토큰발행자 기재
sub
(subject): Subject of the JWT (the user) //토큰제목
aud
(audience): Recipient for which the JWT is intended //토큰사용대상 기재
exp
(expiration time): Time after which the JWT expires //토큰 만료시각
nbf
(not before time): Time before which the JWT must not be accepted for processing //이시각 이후부터 토큰사용가능
iat
(issued at time): Time at which the JWT was issued; can be used to determine age of the JWT //토큰생성시각
jti
(JWT ID): Unique identifier; can be used to prevent the JWT from being replayed (allows a token to be used only once) //토큰ID
2) Slim4 + JWT 적용
firebase/php-jwt [v6.3] 사용(가볍고 심플)
php slim프레임워크 사용 중인 프로젝트 루트 폴더로 이동
cd D:/htdocs/slimproject
composer require firebase/php-jwt
3) 토큰생성
<?php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
# /login : GET + Params
$app->get('/login', function (Request $request, Response $response) {
$data = $request->getQueryParams();
$email = $data["email"];
$pw = $data["pw"];
$key = "example@@key$$";
$payload = [
'iss' => 'sebom.com', //iss: 토큰 발급자 (issuer)
'sub' => 'sebom.com API', //토큰 제목 (subject)
'iat' => time(), //토큰이 발급된 시간 (issued at)
'exp' => time() + (3600 * 3), //time() + (3600 * 3), // 만료기간 3600초(1시간) x 3 = 3시간 후 만료,
'nbf' => time() + (80), //지정한 일시 이후 부터 사용가능한 토큰으로 생성
'email' => $email
];
$jwt = JWT::encode($payload, $key, 'HS256');
$response->getBody()->write($jwt);
return $response
->withHeader('content-type', 'application/json')
->withStatus(200);
});
[Result]
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzZWJvbS5jb20iLCJzdWIiOiJzZWJvbS5jb20gQVBJIiwiaWF0IjoxNjcyNDUwMjU2LCJleHAiOjE2NzI4MTAyNTYsIm5iZiI6MTY3MjQ1MDMzNiwiZW1haWwiOiJjY0BnbWFpbC5jb20ifQ.YC-MQxBKbSnXVH7P_wJHTIfUwcTyNLQL-W9hV8v0xJ4
4) 생성토큰 디코딩
use Firebase\JWT\JWT;
# /loginckeck : GET + Params
$app->get(
'/logincheck',
function (Request $request, Response $response, array $args) {
$data = $request->getQueryParams();
$jwt = $data["jwt"];
$key = "example@@key$$";
JWT::$leeway = 60; //비교 시간 검증 전후 여유(60초)
$decoded = JWT::decode($jwt, new key($key, 'HS256')); //stdclass 로 리턴됨
$response->getBody()->write($decoded->email); //stdclass를 array 로 변환하거나, $decoded->email 로 문자열(값) 받음.
//stdclass를 array 로 변환 예제
//$decoded_array = (array) $decoded;
//$response->getBody()->write($decoded_array['email']);
return $response;
}
);
[Result]
5) 기타
JWT::$leeway = 60; //토큰 디코딩 하기전에 설정
---------------------
firebase/php-jwt 에서 JWT::$leeway 값에 초 단위 숫자를 지정하면, 기본값은 0
JWT 의 시간대조(만료시각 또는 nbf 시각) 로직에서 실정한 시간 만큼의 전후 여유(시간 오차)를 허용[true]해 준다. - 응답 딜레이 대응
1분 이내의 값을 권장한다.
Registered claims => nbf ? (Not before)
----------------------
로그인한 사용자에게 토큰을 발행해 주지만, 관리자가 어떤 확인 작업을 마친 후 1시간 이후 부터 그 토큰을 사용할 수 있게 하고 싶다면.
'nbf' => time() + (3600 * 1) //지정한 일시 이후 부터 사용가능한 토큰으로 생성
예) JWT::$leeway 와 nbf 관계 예시
※ 토큰생성시 'nbf' => time() + (10)
디코딩시 JWT::$leeway = 60; 설정 조건이라면..
이 토큰은 토큰 생성 후 10초 이후부터 토큰 사용이 가능하다. 'nbf' => time() + (10)
그러나, 디코딩시 JWT::$leeway = 60; 설정 조건이 있으므로 60초 이내 범위는 허용(true)되어 10초 이전에도 바로 토큰 사용이 가능해진다.
※ 토큰생성시 'nbf' => time() + (80)
디코딩시 JWT::$leeway = 60; 설정 조건이라면..
이 토큰은 토큰 생성 후 80초 이후부터 토큰 사용이 가능하다. 'nbf' => time() + (80)
그러나, 디코딩시 JWT::$leeway = 60; 설정 조건이 있으므로 60초 이내 범위는 허용되어 20초(80초-60초) 이후에 토큰 사용이 가능하다.