New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BE] issue229: Refresh Token 적용하기 #236
Changes from all commits
17cacfa
b105b4b
195b324
722d777
f907ff7
beeaaf0
9c81970
59e7cae
6ac4158
c8075b8
16ff262
61c6eaf
e328774
d993981
2ad2c9b
013715f
59caef8
bf7ea03
f6235b6
3e4c716
e3d8c52
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.woowacourse.moamoa.auth.domain; | ||
|
||
import static javax.persistence.GenerationType.IDENTITY; | ||
import static lombok.AccessLevel.PROTECTED; | ||
|
||
import javax.persistence.Column; | ||
import javax.persistence.Entity; | ||
import javax.persistence.GeneratedValue; | ||
import javax.persistence.Id; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity | ||
@Getter | ||
@NoArgsConstructor(access = PROTECTED) | ||
@AllArgsConstructor | ||
public class Token { | ||
|
||
@Id | ||
@GeneratedValue(strategy = IDENTITY) | ||
private Long id; | ||
|
||
@Column(nullable = false) | ||
private Long githubId; | ||
|
||
private String refreshToken; | ||
|
||
public Token(final Long githubId, final String refreshToken) { | ||
this(null, githubId, refreshToken); | ||
} | ||
|
||
public void updateRefreshToken(final String refreshToken) { | ||
this.refreshToken = refreshToken; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.woowacourse.moamoa.auth.domain.repository; | ||
|
||
import com.woowacourse.moamoa.auth.domain.Token; | ||
import java.util.Optional; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface TokenRepository extends JpaRepository<Token, Long> { | ||
|
||
Optional<Token> findByGithubId(Long githubId); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.woowacourse.moamoa.auth.exception; | ||
|
||
import com.woowacourse.moamoa.common.exception.UnauthorizedException; | ||
|
||
public class RefreshTokenExpirationException extends UnauthorizedException { | ||
public RefreshTokenExpirationException() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 한 칸 띄워도 좋을 것 같아요 ~ |
||
super("만료된 리프래시 토큰입니다."); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.woowacourse.moamoa.auth.exception; | ||
|
||
import com.woowacourse.moamoa.common.exception.UnauthorizedException; | ||
|
||
public class TokenExpirationException extends UnauthorizedException { | ||
|
||
public TokenExpirationException() { | ||
super("만료된 토큰입니다."); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.woowacourse.moamoa.auth.exception; | ||
|
||
import com.woowacourse.moamoa.common.exception.UnauthorizedException; | ||
|
||
public class TokenNotFoundException extends UnauthorizedException { | ||
|
||
public TokenNotFoundException() { | ||
super("토큰이 존재하지 않습니다."); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
package com.woowacourse.moamoa.auth.infrastructure; | ||
|
||
import com.woowacourse.moamoa.auth.exception.RefreshTokenExpirationException; | ||
import com.woowacourse.moamoa.auth.service.response.TokensResponse; | ||
import io.jsonwebtoken.Claims; | ||
import io.jsonwebtoken.Jws; | ||
import io.jsonwebtoken.JwtException; | ||
|
@@ -15,6 +17,8 @@ | |
@Component | ||
public class JwtTokenProvider implements TokenProvider { | ||
|
||
private static final long REFRESH_TOKEN_EXPIRATION = 7 * 24 * 60 * 60 * 1000; // 7일 | ||
|
||
private final SecretKey key; | ||
private final long validityInMilliseconds; | ||
|
||
|
@@ -27,16 +31,23 @@ public JwtTokenProvider( | |
} | ||
|
||
@Override | ||
public String createToken(final Long payload) { | ||
public TokensResponse createToken(final Long payload) { | ||
final Date now = new Date(); | ||
final Date validity = new Date(now.getTime() + validityInMilliseconds); | ||
|
||
return Jwts.builder() | ||
String accessToken = Jwts.builder() | ||
.setSubject(payload.toString()) | ||
.setIssuedAt(now) | ||
.setExpiration(validity) | ||
.setExpiration(new Date(now.getTime() + validityInMilliseconds)) | ||
.signWith(key, SignatureAlgorithm.HS256) | ||
.compact(); | ||
|
||
String refreshToken = Jwts.builder() | ||
.setIssuedAt(now) | ||
.setExpiration(new Date(now.getTime() + REFRESH_TOKEN_EXPIRATION)) | ||
.signWith(key, SignatureAlgorithm.HS256) | ||
.compact(); | ||
|
||
return new TokensResponse(accessToken, refreshToken); | ||
} | ||
|
||
@Override | ||
|
@@ -57,11 +68,47 @@ public boolean validateToken(final String token) { | |
.build() | ||
.parseClaimsJws(token); | ||
|
||
return !claims.getBody() | ||
.getExpiration() | ||
.before(new Date()); | ||
Date tokenExpirationDate = claims.getBody().getExpiration(); | ||
validateTokenExpiration(tokenExpirationDate); | ||
|
||
return true; | ||
} catch (JwtException | IllegalArgumentException e) { | ||
return false; | ||
} | ||
} | ||
|
||
@Override | ||
public String recreationAccessToken(final Long githubId, final String refreshToken) { | ||
Jws<Claims> claims = Jwts.parserBuilder() | ||
.setSigningKey(key) | ||
.build() | ||
.parseClaimsJws(refreshToken); | ||
|
||
Date tokenExpirationDate = claims.getBody().getExpiration(); | ||
validateTokenExpiration(tokenExpirationDate); | ||
|
||
return createAccessToken(githubId); | ||
} | ||
|
||
private void validateTokenExpiration(Date tokenExpirationDate) { | ||
if (tokenExpirationDate.before(new Date())) { | ||
throw new RefreshTokenExpirationException(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 기존 코드도 401 에러를 던질 것 같은데, 예외 메시지를 다르게 주기 위함인가요 ?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵..!! 로그아웃 시켜야 할 때 코드(4001) 도 함께 전달해달라는 front 측의 요구사항을 반영하기 위해서 였습니다!! |
||
} | ||
} | ||
|
||
private String createAccessToken(final Long githubId) { | ||
final Date now = new Date(); | ||
|
||
return Jwts.builder() | ||
.setSubject(Long.toString(githubId)) | ||
.setIssuedAt(now) | ||
.setExpiration(new Date(now.getTime() + validityInMilliseconds)) | ||
.signWith(key, SignatureAlgorithm.HS256) | ||
.compact(); | ||
} | ||
|
||
@Override | ||
public long getValidityInMilliseconds() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 앗..!! 수정하도록 하겠습니다! |
||
return validityInMilliseconds; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,16 @@ | ||
package com.woowacourse.moamoa.auth.infrastructure; | ||
|
||
import com.woowacourse.moamoa.auth.service.response.TokensResponse; | ||
|
||
public interface TokenProvider { | ||
|
||
String createToken(final Long payload); | ||
TokensResponse createToken(final Long payload); | ||
|
||
String getPayload(final String token); | ||
|
||
boolean validateToken(final String token); | ||
|
||
String recreationAccessToken(final Long githubId, final String refreshToken); | ||
|
||
long getValidityInMilliseconds(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
굿!