Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
37 changes: 34 additions & 3 deletions Application/Infra/Tests/Service/FunctionAPIEndpointTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,47 @@ 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"

#expect(fullName.displayName == "Apple")
}
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