Authorization Server - Token

Dannyยท2024๋…„ 2์›” 2์ผ
0

๋ฐฑ์—”๋“œ

๋ชฉ๋ก ๋ณด๊ธฐ
10/10
๐Ÿ’ก ์˜ค๋Š˜์˜ ๋ชฉํ‘œ๋ฅผ ์„ธ๋ถ„ํ™”ํ•˜์—ฌ ๊ณ„ํšํ•˜๊ณ , ๊ฐ ์„ธ์…˜ ๋ณ„ ์ง„ํ–‰์ƒํ™ฉ์„ ๊ด€๋ฆฌํ•˜์„ธ์š”

ํ† ํฐ๊ด€๋ฆฌ

AccessToken

RefreshToken

  • Redis DB ์„ค์ •
  • AccessToken ์ฝ”๋“œ ์„ค์ •
  • RefreshToken ์ฝ”๋“œ ์„ค์ •

2024๋…„ 1์›” 4์ผ ์˜ค์ „ 10:01


ํ† ํฐ๊ด€๋ฆฌ

ํ† ํฐ๊ด€๋ฆฌ์— ๋Œ€ํ•ด์„œ ๊นŠ๊ฒŒ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€

์ง€๊ธˆ๊นŒ์ง€ ์ธ์ฆ ๋ฐ ์ธ๊ฐ€๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ Access token๋งŒ ์‚ฌ์šฉํ–ˆ์—ˆ๋Š”๋ฐ Access token์˜ ํ•œ๊ณ„๋ฅผ ๋Š๊ปด์„œ Refresh token์„ ์ ์šฉํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

Redis DB์— ๋„ฃ์–ด์„œ ๊ด€๋ฆฌํ•˜๋ฉด ์–ด๋–จ๊นŒ ์ƒ๊ฐํ–ˆ๋‹ค.

1. ํ† ํฐ์ด ๋งŒ๋ฃŒ๋  ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ๋กœ๊ทธ์ธ์„ ํ•ด์•ผ ํ•œ๋‹ค.

  • access token์„ ๋ฐœ๊ธ‰ํ•  ๋•Œ ์œ ํšจ ๊ธฐ๊ฐ„์„ ์ •ํ•ด์„œ ๋ฐœ๊ธ‰์„ ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์ด ์œ ํšจ ๊ธฐ๊ฐ„์ด ์ง€๋‚  ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ๋กœ๊ทธ์ธ์„ ํ•ด์•ผ ํ•œ๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ ์ด ์œ ํšจ ๊ธฐ๊ฐ„์ด ๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉ ์ค‘์ผ ๋•Œ ๋งŒ๋ฃŒ๊ฐ€ ๋œ๋‹ค๋ฉด ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ๋Š” ๋งค์šฐ ๋ถˆํŽธํ•  ๊ฒƒ์ด๋‹ค.
  • ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฉ”๋ชจ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•œ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ ์—ด์‹ฌํžˆ ๋ฉ”๋ชจ๋ฅผ ์ž‘์„ฑํ•˜๋˜ ์ค‘์— ํ† ํฐ์ด ๋งŒ๋ฃŒ๋œ๋‹ค๋ฉด ๋ฉ”๋ชจ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ์‹œ์ ์— ์žฌ๋กœ๊ทธ์ธ์„ ํ•ด์•ผ ํ• ํ…Œ๊ณ  ์ฃผ๊ธฐ์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฅผ ์ €์žฅํ•˜๋Š” ๋กœ์ง์„ ๋”ฐ๋กœ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ํ•ด๋‹น ์ •๋ณด๋ฅผ ๋‹ค์‹œ ์ž…๋ ฅํ•ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค.
  • ์‚ฌ์šฉ์ž์˜ ์ด๋Ÿฌํ•œ ๋ถˆํŽธํ•จ์„ ์—†์• ์•ผ ํ•œ๋‹ค.
  • ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” access token์˜ ์œ ํšจ ๊ธฐ๊ฐ„์„ ๋Š˜๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค.
  • ํ•˜์ง€๋งŒ ์ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์œ„ํ—˜์ด ์กด์žฌํ•œ๋‹ค.

2. ํ† ํฐ์˜ ์œ ํšจ ๊ธฐ๊ฐ„์ด ๊ธธ๋‹ค๋ฉด ํƒˆ์ทจ๋‹นํ–ˆ์„ ๋•Œ ์œ„ํ—˜ํ•˜๋‹ค.

ํ† ํฐ์˜ ์œ ํšจ ๊ธฐ๊ฐ„์„ ๊ธธ๊ฒŒ ์„ค์ •ํ•œ๋‹ค๋ฉด ํ•ด๋‹น ํ† ํฐ์„ ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ ํƒˆ์ทจ๋‹นํ–ˆ์„ ๋•Œ ๊ธด ๊ธฐ๊ฐ„ ๋™์•ˆ ์‚ฌ์šฉ์ž์ธ ์ฒ™ ์š”์ฒญ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ž˜์„œ access token์˜ ์œ ํšจ ๊ธฐ๊ฐ„์„ ์งง๊ฒŒ ํ•ด์„œ ํƒˆ์ทจ๋‹นํ–ˆ์„ ๋•Œ ์œ„ํ—˜์„ ์ค„์—ฌ์•ผ ํ•œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ access token์˜ ์œ ํšจ ๊ธฐ๊ฐ„์„ ์งง๊ฒŒ ํ•œ๋‹ค๋ฉด 1๋ฒˆ ๋ฌธ์ œ๊ฐ€ ๋‹ค์‹œ ๋ฐœ์ƒํ•œ๋‹ค.

๊ฒฐ๊ตญ access token ํ•˜๋‚˜๋งŒ์œผ๋กœ๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ๋ชจ๋‘ ํ•ด๊ฒฐํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค.

์ด ๋•Œ refresh token์„ ๋„์ž…ํ•œ๋‹ค๋ฉด ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

**RedisConnection, RedisConnectionFactory**

์ด๋Ÿฌํ•œ RedisConnection์€ RedisConnectionFactory๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ๋˜๊ณ  ์ด RedisConnectionFactory๊ฐ€ PersistenceExceptionTranslator ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

์ธ์ฆ ์ˆœ์„œ

  1. ์œ ์ €๊ฐ€ ํ† ํฐ ์š”์ฒญ์„ ํ•˜๋ฉด ์„œ๋ฒ„์—์„œ access token๊ณผ refresh token์„ ๋ฐœ๊ธ‰ํ•ด์ค€๋‹ค.
  2. ์œ ์ €๋Š” access token๊ณผ refresh token์„ ์•ˆ์ „ํ•œ ์ €์žฅ์†Œ์— ๋ณด๊ด€ํ•ด๋‘”๋‹ค.
  3. ์œ ์ €๋Š” ์ธ์ฆ์ด ํ•„์š”ํ•œ ์ž‘์—…์„ ํ•  ๋•Œ access token์„ ์„œ๋ฒ„์—๊ฒŒ ๋ณด๋‚ธ๋‹ค.
  4. ์„œ๋ฒ„๋Š” access token์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•œ ๋’ค ์œ ํšจํ•˜๋‹ค๋ฉด ์ž‘์—…์„ ํ—ˆ์šฉํ•œ๋‹ค.
  5. access token์ด ๋งŒ๋ฃŒ๋˜์—ˆ๋‹ค๋ฉด ์„œ๋ฒ„๋Š” access token์ด ๋งŒ๋ฃŒ๋˜์—ˆ๋‹ค๋Š” ์‘๋‹ต์„ ๋‚ด๋ ค์ค€๋‹ค.
  6. ์œ ์ €๋Š” refresh token์„ ์„œ๋ฒ„์—๊ฒŒ ๋ณด๋‚ธ๋‹ค.
  7. refresh token์ด ์œ ํšจํ•˜๋‹ค๋ฉด ์ƒˆ๋กœ์šด access token์„ ๋ฐœ๊ธ‰ํ•ด์ฃผ๊ณ  ์œ ์ €๋Š” ์ด access token์œผ๋กœ ๋‹ค์‹œ ์ž‘์—…์„ ์š”์ฒญํ•œ๋‹ค.
  8. refresh token์ด ์œ ํšจํ•˜์ง€ ์•Š๋‹ค๋ฉด ๋‹ค์‹œ ๋กœ๊ทธ์ธ์„ ํ•˜๋„๋ก ์‘๋‹ต์„ ๋‚ด๋ ค์ค€๋‹ค.

๋‹จ, RefreshToken์ด ํƒˆ์ทจ๋‹นํ•œ๋‹ค๋ฉด ๋ฌด์ œํ•œ AccessToken์ด ๋ฐœ๊ธ‰๋œ๋‹ค.
ํ•˜๊ณ  ์ถ”๊ฐ€๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ refresh token๊ณผ ๋™์ผํ•œ์ง€ ํ™•์ธํ•œ๋‹ค.

์ฆ‰, access token์„ ์žฌ๋ฐœ๊ธ‰ ํ•  ๋•Œ refresh token๋„ ์žฌ๋ฐœ๊ธ‰ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

  • token rotation์„ ์ ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— refresh token์˜ ์œ ํšจ ๊ธฐ๊ฐ„์ด ๊ธธ๋”๋ผ๋„ ๊ฐ’์ด ๊ณ„์† ๊ฐฑ์‹ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธด ์œ ํšจ ๊ธฐ๊ฐ„์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์ธ์ฆ์ˆœ์„œ

  1. ์œ ์ €๊ฐ€ ๋กœ๊ทธ์ธ์„ ํ•˜๋ฉด ์„œ๋ฒ„์—์„œ access token๊ณผ refresh token์„ ๋ฐœ๊ธ‰ํ•˜๊ณ  refresh token์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•ด๋‘”๋‹ค.
  2. ์œ ์ €๋Š” access token๊ณผ refresh token์„ ์•ˆ์ „ํ•œ ์ €์žฅ์†Œ์— ๋ณด๊ด€ํ•ด๋‘”๋‹ค.
  3. ์œ ์ €๋Š” ์ธ์ฆ์ด ํ•„์š”ํ•œ ์ž‘์—…์„ ํ•  ๋•Œ access token์„ ์„œ๋ฒ„์—๊ฒŒ ๋ณด๋‚ธ๋‹ค.
  4. ์„œ๋ฒ„๋Š” access token์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•œ ๋’ค ์œ ํšจํ•˜๋‹ค๋ฉด ์ž‘์—…์„ ํ—ˆ์šฉํ•œ๋‹ค.
  5. access token์ด ๋งŒ๋ฃŒ๋˜์—ˆ๋‹ค๋ฉด ์„œ๋ฒ„๋Š” access token์ด ๋งŒ๋ฃŒ๋˜์—ˆ๋‹ค๋Š” ์‘๋‹ต์„ ๋‚ด๋ ค์ค€๋‹ค.
  6. ์œ ์ €๋Š” refresh token์„ ์„œ๋ฒ„์—๊ฒŒ ๋ณด๋‚ธ๋‹ค.
  7. refresh token์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ refresh token๊ณผ ๋™์ผํ•œ์ง€ ํ™•์ธํ•œ๋‹ค.
  8. ์œ ํšจํ•˜๊ณ  ๋™์ผํ•˜๋‹ค๋ฉด access token์„ ๋ฐœ๊ธ‰ํ•ด์ค€๋‹ค.
  9. ์œ ํšจํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ๋™์ผํ•˜์ง€ ์•Š๋‹ค๋ฉด refresh token์„ ์‚ญ์ œํ•˜๊ณ  ๋‹ค์‹œ ๋กœ๊ทธ์ธ์„ ํ•˜๋„๋ก ์‘๋‹ต์„ ๋‚ด๋ ค์ค€๋‹ค.

Redis

https://bcp0109.tistory.com/328

SpringBoot

๊ธฐ์กด ์ง„ํ–‰ ์ค‘์ธ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•œ๋‹ค๋ฉด build.gradle์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

build.gradle{
	implementation 'org.springframework.boot:spring-boot-starter-data-redis'
}

application.yml , application.propertice ์ ์šฉ

spring.redis.host=localhost
spring.redis.port=6379

redis java client๋Š” lettuce์™€ jedis๊ฐ€ ์žˆ๋Š”๋ฐ lettuce๋Š” ๋ณ„๋‹ค๋ฅธ ์„ค์ • ์—†์ด ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ lettuce๋กœ ์ง„ํ–‰ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

LettuceConnectionFactory๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

@Configuration
class RedisConfig {
  @Bean
  public RedisConnectionFactory redisConnectionFactory() {

    return new LettuceConnectionFactory(
    	new RedisStandaloneConfiguration("ํ˜ธ์ŠคํŠธ", 6379)
    );
  }
}

RedisStandaloneConfiguration์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž์—” ํ˜ธ์ŠคํŠธ, ๋‘ ๋ฒˆ์งธ ์ธ์ž์—” ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.
LettuceConnectionFactory๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑ๋œ Lettuce๋Š” ๋™์ผํ•œ thread-safe connection์„ ๊ณต์œ ํ•œ๋‹ค.

RedisTemplate

RedisConnection์˜ ๊ฒฝ์šฐ binary valuef๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š”๋ฐ RedisTemplate์˜ ๊ฒฝ์šฐ ๋†’์€ ์ˆ˜์ค€์˜ ์ถ”์ƒํ™”์™€ ์ง๋ ฌํ™”๋ฅผ ์ œ๊ณตํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ํŽธํ•˜๋‹ค.

RedisTemplate์€ ๋‹ค์–‘ํ•œ ํƒ€์ž…์— ๋Œ€ํ•ด ๋‹ค์–‘ํ•œ ์—ฐ์‚ฐ์„ ์ œ๊ณตํ•ด์ค€๋‹ค.

ํŠน์ • ํ‚ค ๊ฐ’์— ๋Œ€ํ•ด value๋ฅผ string, list, set ... ๋“ฑ๋“ฑ ๋งŽ์€ ์—ฐ์‚ฐ์„ ์ œ๊ณตํ•ด์ค€๋‹ค.

key bound๋ฅผ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ํƒ€์ž…์˜ key๋„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

RedisConnectionFactory์— ์ด์–ด RedisTemplate๋„ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด๋ณด์ž.

@Configuration
public class RedisConfiguration {
    @Value("${spring.redis.host}")
    private String redisHost;
    @Value("${spring.redis.port}")
    private int redisPort;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(redisHost, redisPort);
    }
    @Bean
    public RedisTemplate<String, String> redisTemplate() {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}

0๊ฐœ์˜ ๋Œ“๊ธ€