Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Application/Infra/Sources/Service/FunctionAPIClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ struct FirebaseCustomTokenResponse: Decodable {
struct AppleCustomTokenRequest: Encodable {
let challengeId: String
let authorizationCode: String
let displayName: String?
}

struct AppleAccountLinkRequest: Encodable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,38 +42,18 @@ final class AppleAuthenticationServiceImpl: AuthenticationService {
let response = try await authenticateWithAppleAsync(
hashedNonce: challenge.hashedNonce
)


let displayName = response.fullName?.displayName
Comment thread
opficdev marked this conversation as resolved.

logger.debug("Requesting custom token from Firebase Function")
let customToken = try await requestAppleCustomToken(
challengeId: challenge.challengeId,
authorizationCode: response.authorizationCode
authorizationCode: response.authorizationCode,
displayName: displayName
)

logger.debug("Signing in with custom token")
let result = try await Auth.auth().signIn(withCustomToken: customToken)

let changeRequest = result.user.createProfileChangeRequest()
var displayName: String?

if let fullName = response.fullName {
let formatter = PersonNameComponentsFormatter()
formatter.style = .long
let formattedName = formatter.string(from: fullName)
if !formattedName.isEmpty {
displayName = formattedName
}
}

if displayName == nil {
let doc = try await store
.document(FirestorePath.userData(result.user.uid, document: .info))
.getDocument()
displayName = doc.data()?["appleName"] as? String
}

changeRequest.displayName = displayName ?? ""
changeRequest.photoURL = nil // Apple ID 프로필 사진 URL은 제공되지 않음
try await changeRequest.commitChanges()

logger.info("Successfully signed in with Apple")
return result.user.makeResponse(providerID: .apple)
Expand Down Expand Up @@ -224,13 +204,15 @@ final class AppleAuthenticationServiceImpl: AuthenticationService {

private func requestAppleCustomToken(
challengeId: String,
authorizationCode: String
authorizationCode: String,
displayName: String?
) async throws -> String {
let response = try await FunctionAPIClient.shared.send(
.requestAppleCustomToken,
payload: AppleCustomTokenRequest(
challengeId: challengeId,
authorizationCode: authorizationCode
authorizationCode: authorizationCode,
displayName: displayName
),
requiresAuthentication: false
)
Expand All @@ -239,6 +221,15 @@ final class AppleAuthenticationServiceImpl: AuthenticationService {
}
}

extension PersonNameComponents {
var displayName: String? {
let formatter = PersonNameComponentsFormatter()
formatter.style = .long
let name = formatter.string(from: self)
return name.isEmpty ? nil : name
}
}
Comment thread
opficdev marked this conversation as resolved.

private extension AppleAuthenticationServiceImpl {
func mapAppleAPIError(_ error: Error) -> Error {
if let emailError = error.apiEmailError {
Expand Down
38 changes: 35 additions & 3 deletions Application/Infra/Tests/Service/FunctionAPIEndpointTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,48 @@ struct FunctionAPIEndpointTests {
#expect(endpoint.path == "/auth/apple/access-token")
}

@Test("Apple custom token 요청은 challenge와 authorization code만 인코딩한다")
func Apple_custom_token_요청은_challenge와_authorization_code만_인코딩한다() throws {
@Test("Apple custom token 요청은 display name을 포함할 수 있다")
func Apple_custom_token_요청은_display_name을_포함할_수_있다() throws {
let request = AppleCustomTokenRequest(
challengeId: "challenge-id",
authorizationCode: "authorization-code"
authorizationCode: "authorization-code",
displayName: "Apple User"
)

#expect(
try encodedKeys(request) == [
"challengeId",
"authorizationCode",
"displayName"
]
)
}

@Test("Apple custom token 요청은 없는 display name을 인코딩하지 않는다")
func Apple_custom_token_요청은_없는_display_name을_인코딩하지_않는다() throws {
let request = AppleCustomTokenRequest(
challengeId: "challenge-id",
authorizationCode: "authorization-code",
displayName: nil
)

#expect(try encodedKeys(request) == ["challengeId", "authorizationCode"])
}

@Test("Apple 이름은 custom token 요청용 display name으로 변환한다")
func Apple_이름은_custom_token_요청용_display_name으로_변환한다() {
var fullName = PersonNameComponents()
fullName.givenName = "Apple"
fullName.familyName = "User"

#expect(fullName.displayName == "Apple User")
}
Comment thread
opficdev marked this conversation as resolved.

@Test("비어 있는 Apple 이름은 display name으로 변환하지 않는다")
func 비어_있는_Apple_이름은_display_name으로_변환하지_않는다() {
#expect(PersonNameComponents().displayName == nil)
}
Comment thread
opficdev marked this conversation as resolved.

@Test("Apple 계정 연결 요청은 credential email을 포함할 수 있다")
func Apple_계정_연결_요청은_credential_email을_포함할_수_있다() throws {
let request = AppleAccountLinkRequest(
Expand Down
Loading