Skip to content

Commit

Permalink
[MERGE] Merge pull request #223 from Team-WSS/fix/#220
Browse files Browse the repository at this point in the history
[FIX] 애플 소셜 로그인 방식 수정
  • Loading branch information
ChaeAg authored Nov 13, 2024
2 parents c27f81a + 3dd46e9 commit cee6abe
Show file tree
Hide file tree
Showing 13 changed files with 397 additions and 21 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/CD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ jobs:
echo "${{ secrets.APPLICATION }}" > ./application.yml
echo "${{ secrets.APPLICATION_PROD }}" > ./application-prod.yml
- name: Create apple login key file
env:
API_KEY: ${{ secrets.APPSTORE_API_KEY_ID }}
run: |
mkdir -p src/main/resources/static
echo "${{ secrets.APPLE_AUTH_KEY }}" > src/main/resources/static/AuthKey_$API_KEY.p8
- name: Grant execute permission for gradlew
run: chmod +x gradlew
shell: bash
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ jobs:
echo "${{ secrets.APPLICATION }}" > ./application.yml
echo "${{ secrets.APPLICATION_PROD }}" > ./application-prod.yml
- name: Create apple login key file
env:
API_KEY: ${{ secrets.APPSTORE_API_KEY_ID }}
run: |
mkdir -p src/main/resources/static
echo "${{ secrets.APPLE_AUTH_KEY }}" > src/main/resources/static/AuthKey_$API_KEY.p8
- name: Grant execute permission for gradlew
run: chmod +x gradlew
shell: bash
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ out/

## QClass ##
src/main/generated/

## Apple Login Key File ##
*.p8
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ dependencies {
// spring data redis
implementation 'org.springframework.data:spring-data-redis:3.3.2'

//Apple Login
implementation 'com.nimbusds:nimbus-jose-jwt:3.10'

//Json
implementation 'com.googlecode.json-simple:json-simple:1.1.1'

//Apple Login
implementation 'com.nimbusds:nimbus-jose-jwt:3.10'
}

tasks.named('test') {
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/org/websoso/WSSServer/domain/UserAppleToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.websoso.WSSServer.domain;

import static jakarta.persistence.GenerationType.IDENTITY;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserAppleToken {

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(nullable = false)
private Long userAppleTokenId;

@Column(nullable = false)
private String appleRefreshToken;

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

private UserAppleToken(User user, String appleRefreshToken) {
this.user = user;
this.appleRefreshToken = appleRefreshToken;
}

public static UserAppleToken create(User user, String appleRefreshToken) {
return new UserAppleToken(user, appleRefreshToken);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package org.websoso.WSSServer.dto.auth;

import jakarta.annotation.Nullable;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;

public record AppleLoginRequest(
@NotBlank(message = "사용자 고유 식별자는 null 이거나, 공백일 수 없습니다.")
String userIdentifier,
@Pattern(regexp = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,6}$", message = "이메일 형식이 올바르지 않습니다.")
@Nullable
String email
@NotBlank(message = "애플 인증 코드 값은 null 이거나, 공백일 수 없습니다.")
String authorizationCode,
@NotBlank(message = "애플 ID 토큰 값은 null 이거나, 공백일 수 없습니다.")
String idToken
) {
}
37 changes: 37 additions & 0 deletions src/main/java/org/websoso/WSSServer/dto/auth/ApplePublicKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.websoso.WSSServer.dto.auth;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public record ApplePublicKey(
String kty,
String kid,
String use,
String alg,
String n,
String e
) {

public boolean isSameAlg(final String alg) {
return this.alg.equals(alg);
}

public boolean isSameKid(final String kid) {
return this.kid.equals(kid);
}

@JsonCreator
public ApplePublicKey(@JsonProperty("kty") final String kty,
@JsonProperty("kid") final String kid,
@JsonProperty("use") final String use,
@JsonProperty("alg") final String alg,
@JsonProperty("n") final String n,
@JsonProperty("e") final String e) {
this.kty = kty;
this.kid = kid;
this.use = use;
this.alg = alg;
this.n = n;
this.e = e;
}
}
18 changes: 18 additions & 0 deletions src/main/java/org/websoso/WSSServer/dto/auth/ApplePublicKeys.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.websoso.WSSServer.dto.auth;

import static org.websoso.WSSServer.exception.error.CustomAppleLoginError.INVALID_APPLE_KEY;

import java.util.List;
import org.websoso.WSSServer.exception.exception.CustomAppleLoginException;

public record ApplePublicKeys(
List<ApplePublicKey> keys
) {

public ApplePublicKey getMatchingKey(final String alg, final String kid) {
return keys.stream()
.filter(key -> key.isSameAlg(alg) && key.isSameKid(kid))
.findFirst()
.orElseThrow(() -> new CustomAppleLoginException(INVALID_APPLE_KEY, "invalid apple key"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.websoso.WSSServer.dto.auth;

public record AppleTokenResponse(
String access_token,
String expires_in,
String id_token,
String refresh_token,
String token_type,
String error
) {

public String getAccessToken() {
return access_token;
}

public String getIdToken() {
return id_token;
}

public String getRefreshToken() {
return refresh_token;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.NOT_FOUND;

import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -13,12 +12,15 @@
@Getter
public enum CustomAppleLoginError implements ICustomError {

MISSING_AUTHORIZATION_CODE("APPLE-001", "인증 코드를 입력하지 않았습니다.", BAD_REQUEST),
TOKEN_REQUEST_FAILED("APPLE-003", "Apple 서버로부터 토큰을 받아오지 못했습니다.", INTERNAL_SERVER_ERROR),
ID_TOKEN_PARSE_FAILED("APPLE-004", "Apple ID 토큰을 파싱하지 못했습니다.", INTERNAL_SERVER_ERROR),
USER_INFO_RETRIEVAL_FAILED("APPLE-005", "Apple에서 사용자 정보를 가져오지 못했습니다.", NOT_FOUND),
CLIENT_SECRET_CREATION_FAILED("APPLE-006", "클라이언트 시크릿을 생성하는 데 실패했습니다.", INTERNAL_SERVER_ERROR),
PRIVATE_KEY_READ_FAILED("APPLE-007", "프라이빗 키를 읽는 데 실패했습니다.", INTERNAL_SERVER_ERROR);
TOKEN_REQUEST_FAILED("APPLE-001", "Apple 서버로부터 토큰을 받아오지 못했습니다.", INTERNAL_SERVER_ERROR),
CLIENT_SECRET_CREATION_FAILED("APPLE-002", "클라이언트 시크릿을 생성하는 데 실패했습니다.", INTERNAL_SERVER_ERROR),
PRIVATE_KEY_READ_FAILED("APPLE-003", "프라이빗 키를 읽는 데 실패했습니다.", INTERNAL_SERVER_ERROR),
INVALID_APPLE_TOKEN_FORMAT("APPLE-004", "idToken 값이 jwt 형식인지 확인이 필요합니다.", BAD_REQUEST),
HEADER_PARSING_FAILED("APPLE-005", "디코드된 헤더를 Map 형태로 변환할 수 없습니다.", INTERNAL_SERVER_ERROR),
UNSUPPORTED_JWT_TYPE("APPLE-006", "지원되지 않는 jwt 타입입니다.", BAD_REQUEST),
EMPTY_JWT("APPLE-007", "비어있는 jwt입니다.", BAD_REQUEST),
JWT_VERIFICATION_FAILED("APPLE-008", "jwt 검증 또는 분석에 실패했습니다.", INTERNAL_SERVER_ERROR),
INVALID_APPLE_KEY("APPLE-009", "잘못된 애플 키입니다.", INTERNAL_SERVER_ERROR);

private final String code;
private final String description;
Expand Down
Loading

0 comments on commit cee6abe

Please sign in to comment.