Skip to content

Commit

Permalink
#31 [FEAT] : 애플 연결 끊기
Browse files Browse the repository at this point in the history
  • Loading branch information
hye-on committed Sep 7, 2023
1 parent 201f481 commit 2e67bc3
Show file tree
Hide file tree
Showing 12 changed files with 218 additions and 19 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,7 @@ application-oauth.properties
togetup-26b96-firebase-adminsdk-3l3ah-3164ed8f18.json

### log files ###
logs
logs

###apple
AuthKey_M992KTZK9V.p8
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
package com.wakeUpTogetUp.togetUp.api.auth.apple;


import com.wakeUpTogetUp.togetUp.api.auth.dto.request.AppleRevokeReq;
import com.wakeUpTogetUp.togetUp.api.auth.dto.request.AppleTokenReq;
import com.wakeUpTogetUp.togetUp.api.auth.dto.response.AppleTokenRes;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

@FeignClient(name = "apple-public-key-client", url = "https://appleid.apple.com/auth")

@FeignClient(name = "apple-public-key-client", url = "https://appleid.apple.com/auth")
public interface AppleClient {

@GetMapping("/keys")
ApplePublicKeys getApplePublicKeys();

@PostMapping(value = "/token",consumes = "application/x-www-form-urlencoded")
AppleTokenRes findAppleToken(@RequestBody AppleTokenReq req);

@PostMapping(value = "/revoke",consumes = "application/x-www-form-urlencoded")
void revoke(AppleRevokeReq req);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.wakeUpTogetUp.togetUp.api.auth.dto.request;

import lombok.Builder;
import lombok.Getter;
import lombok.ToString;

@Getter
@Builder
@ToString
public class AppleRevokeReq {
private String client_id;
private String client_secret;
private String token;
private String token_type_hint;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.wakeUpTogetUp.togetUp.api.auth.dto.request;

import lombok.Builder;
import lombok.Getter;
import lombok.ToString;

@Getter
@Builder
@ToString
public class AppleTokenReq {
private String client_id;
private String client_secret;
private String code;
private String grant_type;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.wakeUpTogetUp.togetUp.api.auth.dto.response;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;

@ToString
@Getter
@JsonIgnoreProperties(ignoreUnknown = true)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class AppleTokenRes {
@JsonProperty(value = "access_token")
String accessToken;
@JsonProperty(value = "expires_in")
Integer expiresIn;
@JsonProperty(value = "id_token")
String idToken;
@JsonProperty(value = "refresh_token")
String refreshToken;
@JsonProperty(value = "token_type")
String tokenType;

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.wakeUpTogetUp.togetUp.api.auth.kakao;

import com.wakeUpTogetUp.togetUp.config.FeignConfiguration;
import com.wakeUpTogetUp.togetUp.config.FeignConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;

import java.util.Map;

@FeignClient(value = "kakaoUser", url="https://kapi.kakao.com", configuration = {FeignConfiguration.class})
@FeignClient(value = "kakaoUser", url="https://kapi.kakao.com", configuration = {FeignConfig.class})
public interface KakaoUserApi {
@GetMapping("/v2/user/me")
ResponseEntity<String> getUserInfo(@RequestHeader Map<String, String> header);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,45 @@
import com.nimbusds.jose.shaded.json.JSONObject;
import com.wakeUpTogetUp.togetUp.api.auth.LoginType;
import com.wakeUpTogetUp.togetUp.api.auth.apple.*;
import com.wakeUpTogetUp.togetUp.api.auth.dto.request.AppleRevokeReq;
import com.wakeUpTogetUp.togetUp.api.auth.dto.request.AppleTokenReq;
import com.wakeUpTogetUp.togetUp.api.auth.dto.response.AppleLoginRes;
import com.wakeUpTogetUp.togetUp.api.auth.dto.response.AppleTokenRes;
import com.wakeUpTogetUp.togetUp.api.auth.dto.response.SocialUserRes;
import com.wakeUpTogetUp.togetUp.common.Constant;
import com.wakeUpTogetUp.togetUp.common.Status;
import com.wakeUpTogetUp.togetUp.exception.BaseException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.HttpClientErrorException;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
Expand All @@ -26,6 +53,12 @@ public class AppleLoginServiceImpl implements SocialLoginService {
private final AppleClient appleClient;
private final PublicKeyGenerator publicKeyGenerator;
private final AppleClaimsValidator appleClaimsValidator;
@Value("${oauth.apple.client-id}")
private String clientId;
@Value("${oauth.apple.iss}")
private String iss;
@Value("${oauth.apple.key-id}")
private String keyId;
@Override
public LoginType getServiceName() {
return LoginType.APPLE;
Expand All @@ -34,7 +67,7 @@ public LoginType getServiceName() {
@Override
public SocialUserRes getUserInfo(String accessToken) {

Map<String, String> headers = appleJwtParser.parseHeaders(accessToken);//안되면 identyfi 토큰으로 바꾸기
Map<String, String> headers = appleJwtParser.parseHeaders(accessToken);
ApplePublicKeys applePublicKeys = appleClient.getApplePublicKeys();

PublicKey publicKey = publicKeyGenerator.generatePublicKey(headers, applePublicKeys);
Expand All @@ -55,4 +88,67 @@ private void validateClaims(Claims claims) {

}
}
public AppleTokenRes getAppleToken(String authorizationCode) throws IOException {

AppleTokenReq appleTokenReq = AppleTokenReq.builder()
.client_id(clientId)
.client_secret(this.createClientSecret())
.code(authorizationCode)
.grant_type("authorization_code")
.build();

return appleClient.findAppleToken(appleTokenReq);
}

public String createClientSecret() throws IOException{



Date expirationDate = Date.from(LocalDateTime.now().plusDays(30).atZone(ZoneId.systemDefault()).toInstant());
return Jwts.builder()
.setHeaderParam("kid", keyId)
.setHeaderParam("alg", "ES256")
.setIssuer(iss)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(expirationDate)
.setAudience("https://appleid.apple.com")
.setSubject(clientId)
.signWith(SignatureAlgorithm.ES256, this.getPrivateKey())
.compact();
}

private PrivateKey getPrivateKey() throws IOException {
ClassPathResource resource = new ClassPathResource("AuthKey_M992KTZK9V.p8");
String privateKey = new String(Files.readAllBytes(Paths.get(resource.getURI())));
Reader pemReader = new StringReader(privateKey);
PEMParser pemParser = new PEMParser(pemReader);
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
PrivateKeyInfo object = (PrivateKeyInfo) pemParser.readObject();
return converter.getPrivateKey(object);
}


public void revoke (String accessToken) throws IOException {
try {
AppleRevokeReq appleRevokeReq = AppleRevokeReq.builder()
.client_id(clientId)
.client_secret(this.createClientSecret())
.token(accessToken)
.token_type_hint("access_token")
.build();
appleClient.revoke(appleRevokeReq);
} catch (HttpClientErrorException e) {
throw new RuntimeException("Apple Revoke Error");
}
}

// @Transactional
// public void appleTest(String authCode) throws IOException {
//
// AppleTokenRes appleToken = this.getAppleToken(authCode);
//
// this.revoke(appleToken.getAccessToken());
// }


}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.wakeUpTogetUp.togetUp.api.auth.service;

import com.wakeUpTogetUp.togetUp.api.auth.dto.response.AppleTokenRes;
import com.wakeUpTogetUp.togetUp.api.auth.dto.response.LoginRes;
import com.wakeUpTogetUp.togetUp.api.auth.LoginType;
import com.wakeUpTogetUp.togetUp.api.auth.dto.request.SocialLoginReq;
Expand All @@ -9,6 +10,8 @@
import com.wakeUpTogetUp.togetUp.api.users.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -24,7 +27,7 @@ public class AuthService {
private final List<SocialLoginService> loginServices;
private final JwtService jwtService;
private final UserRepository userRepository;

private final AppleLoginServiceImpl appleLoginService;


@Transactional
Expand Down Expand Up @@ -82,8 +85,14 @@ private Integer getSignedUserId(SocialUserRes socialUserRes,LoginType loginType
}


@Transactional
public void disconnectApple(String authCode) throws IOException {


AppleTokenRes appleToken = appleLoginService.getAppleToken(authCode);
appleLoginService.revoke(appleToken.getAccessToken());
}


}

Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.wakeUpTogetUp.togetUp.api.users;

import com.wakeUpTogetUp.togetUp.api.auth.AuthUser;
import com.wakeUpTogetUp.togetUp.api.auth.service.AppleLoginServiceImpl;
import com.wakeUpTogetUp.togetUp.api.auth.service.AuthService;
import com.wakeUpTogetUp.togetUp.common.Status;
import com.wakeUpTogetUp.togetUp.common.dto.BaseResponse;
import io.swagger.v3.oas.annotations.Hidden;
Expand All @@ -10,6 +12,10 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

@Tag(name = "유저")
@RestController
@RequiredArgsConstructor
Expand All @@ -18,6 +24,8 @@ public class UserController {

private final UserService userService;
private final UserRepository userRepository;
private final AppleLoginServiceImpl appleLoginService;
private final AuthService authService;


@Operation(summary = "fcmToken 업데이트")
Expand All @@ -34,13 +42,22 @@ public BaseResponse<Status> updateAgreePush(@Parameter(hidden = true) @AuthUser
return new BaseResponse<>(Status.SUCCESS);
}

@Operation(summary="유저 탈퇴")
@Operation(summary="카카오 유저 탈퇴")
@DeleteMapping()
public BaseResponse<Status> deleteUser(@Parameter(hidden = true) @AuthUser Integer userId){
public BaseResponse<Status> deleteKaKaoUser(@Parameter(hidden = true) @AuthUser Integer userId){
userService.deleteById(userId);
return new BaseResponse<>(Status.SUCCESS);
}

@Operation(summary="애플 유저 탈퇴")
@DeleteMapping("test")
public BaseResponse<Status> deleteAppleUser(@Parameter(hidden = true) @AuthUser Integer userId,@RequestParam() String authorizationCode ) throws IOException{
userService.deleteAppleUser(userId,authorizationCode);
return new BaseResponse<>(Status.SUCCESS);
}






Expand Down
21 changes: 13 additions & 8 deletions src/main/java/com/wakeUpTogetUp/togetUp/api/users/UserService.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package com.wakeUpTogetUp.togetUp.api.users;

import com.wakeUpTogetUp.togetUp.api.alarm.AlarmRepository;
import com.wakeUpTogetUp.togetUp.api.auth.AuthUser;
import com.wakeUpTogetUp.togetUp.api.auth.service.AuthService;
import com.wakeUpTogetUp.togetUp.api.room.RoomUserRepository;
import com.wakeUpTogetUp.togetUp.api.users.fcmToken.FcmToken;
import com.wakeUpTogetUp.togetUp.api.users.fcmToken.FcmTokenRepository;
import com.wakeUpTogetUp.togetUp.api.users.model.User;
import com.wakeUpTogetUp.togetUp.common.Status;
import com.wakeUpTogetUp.togetUp.exception.BaseException;
import org.apache.ibatis.jdbc.Null;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;

import java.io.IOException;
import java.util.Objects;


Expand All @@ -24,7 +23,7 @@ public class UserService {
private final UserRepository userRepository;
private final FcmTokenRepository fcmTokenRepository;
private final RoomUserRepository roomUserRepository;
private final AlarmRepository alarmRepository;
private final AuthService authService;


public Integer updateFcmToken(Integer userId, Integer fcmTokenId, String fcmToken) {
Expand Down Expand Up @@ -69,11 +68,17 @@ public void deleteById(Integer userId){
if(roomUserNumber>0)
roomUserRepository.deleteByUserId(userId);

//알람 삭제
Integer alarmNumber =alarmRepository.countByUserId(userId);
}

@Transactional
public void deleteAppleUser(Integer userId,String authorizationCode) throws IOException {

if(alarmNumber>0)
alarmRepository.deleteByUserIdAndRoomIdIsNull(userId);
authService.disconnectApple(authorizationCode);
this.deleteById(userId);
}





}
Loading

0 comments on commit 2e67bc3

Please sign in to comment.