-
Notifications
You must be signed in to change notification settings - Fork 0
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
[#29] 인증 및 인가로직 구현 #62
Conversation
추후 개발 마무리 단계에서의 리펙토링이 필요합니다.
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.
핵심 전달을 위해 음슴체로 적겠습니다.
1. base64 디코딩 에러 발생
Authorization
헤더에bearer: accessToken
을 넣고 api 요청- e.g)
/api/projects
- 해당 토큰을 받은 서버는 파싱 실패
JWTDecoder
클래스에서
이후headerJson
깨짐
- 그런데
payloadJson
은 정상적으로JWTDecoder
에 의해 잘 파싱됨
문제 원인 및 해결
JWT token 생성과정에서 문제가 있었습니다.
기존 코드에서 PREFIX = "Bearer ";
은 아래와 같이 Base64
에 의해 인코딩이 되지 않아서 추후 디코딩할때 파싱문제가 생긴 것입니다.
public String generateRefreshToken(String name, String role, String provider, String distinctId) {
Date now = new Date();
return PREFIX.concat(JWT.create()
.withIssuer("AgileHub")
.withSubject("RefreshToken")
.withClaim("name", name)
.withClaim("role", role)
.withClaim("provider", provider)
.withClaim("distinctId", distinctId)
.withIssuedAt(now)
.withExpiresAt(new Date(now.getTime() + refreshTokenValidationSeconds * 1000))
.sign(Algorithm.HMAC512(secretKey)));
}
위의 generateRefreshToken
과 generateAccessToken
메서드 로직에서 PREFIX
는 아래와 같이 제거하거나 인코딩이 필요합니다.
Bearer을 토큰을 만들때 PREFIX로 붙이지 않아도 문제가 없다는 걸 확인했습니다.
public String generateRefreshToken(String name, String role, String provider, String distinctId) {
Date now = new Date();
return JWT.create()
.withIssuer("AgileHub")
.withSubject("RefreshToken")
.withClaim("name", name)
.withClaim("role", role)
.withClaim("provider", provider)
.withClaim("distinctId", distinctId)
.withIssuedAt(now)
.withExpiresAt(new Date(now.getTime() + refreshTokenValidationSeconds * 1000))
.sign(Algorithm.HMAC512(secretKey));
}
2. NullPointerException 발생
문제 원인
JWTAuthFilter
에서 토큰이 정상적으로 확인이되면 saveAuthentication(accessToken);
으로 해당 accessToken을 추출하여 SecurityContextHolder
의 setAuthentication()
메서드를 통해 SecurityContext
에 인증정보를 저장하는 로직이 있습니다.
그 로직에서 Member
를 찾고 SecurityMember
에 전달합니다. 현재 SecurityMember
에는 UserInfo
가 비어있는 상태입니다
이때 UsernamePasswordAuthenticationToken
에 전달하고 시큐리티 필터 내부에서 getUsername()
메서드를 실행합니다.
그런데 SecurityMember
의 getUsername()
에는
userInfo.getNickname()
으로 로직이 실행되고 있어서 NullPointerException
이 발생합니다.
따라서 getUsername()
을 Member로 하던지(대신 이때 OSIV를 고려해서 해야할거같아서 복잡..)
아니면 OAuth2UserInfo
를 채워주는 로직을 추가적으로 만들어야 할것 같습니다.
src/main/java/dynamicquad/agilehub/global/filter/JwtAuthFilter.java
Outdated
Show resolved
Hide resolved
|
SecurityMember에서 userInfo로 getNickname() 호출 시 NullPointerException 발생. 따라서 member로 getName()을 호출하고, OSIV 옵션이 꺼져있으므로, 서비스 단에서 getName()을 한번 호출해 프록시 객체의 필드가 로드되도록 수정.
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.
LGTM
📄 Summary
Spring Security + OAuth2 + JWT 이용한 인증/인가로직의 구현입니다.
아직 테스트에서 모든 Controller layer가 통과되지 않아 수정이 필요합니다.
🕰️ Actual Time of Completion
1달
🙋🏻 More
{host}/oauth2/auth/kakao
로 get 요청시 쿼리 파라미터를 통해 JWT Access Token이 반환됩니다.oauth 로그인이 성공적인 경우
/auth/success
로 리다이렉트합니다. (수정 가능)프론트는 해당 AccessToken을 Authorization 헤더에 Bearer를 붙여서 요청하면 정상적으로 요청이 반환됩니다.
"Refresh Token은 보안상의 이유로 유저에게 공개되지 않고 백에서 관리합니다."
따라서 만약 Access 토큰이 만료된다면 백 로직에서 Access Token을 재발급하여 프론트로 전달합니다.