ContinueWithApple

Sign in with Apple, Sign up with Apple, or Continue with Apple

Utils

1. randomNonceString

로그인 요청마다 임의의 문자열인 ‘nonce’가 생성되며, 이 ‘nonce’는 앱의 인증 요청에 대한 응답으로 ID 토큰이 명시적으로 부여되었는지 확인하는 데 사용된다. 릴레이 공격을 방지하려면 이 단계가 필요하다.

Adapted from https://auth0.com/docs/api-auth/tutorials/nonce

func randomNonceString(length: Int = 32) -> String {
    precondition(length > 0)
    let charset: Array<Character> =
        Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._")
    var nonce = ""
    var remainingLength = length
    
    while remainingLength > 0 {
        let randoms: [UInt8] = (0 ..< 16).map { _ in
            var random: UInt8 = 0
            /// SecRandomCopyBytes(_:_:_)를 사용하여 암호로 보호된 'nonce' 를 생성한다.
            let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random)
            if errorCode != errSecSuccess {
                fatalError("Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)")
            }
            return random
        }
        
        randoms.forEach { random in
            if remainingLength == 0 {
                return
            }
            
            if random < charset.count {
                nonce.append(charset[Int(random)])
                remainingLength -= 1
            }
        }
    }
    
    return nonce
}

2. Secure Hashing Algorithm

256비트 다이제스트를 사용한 SHA-2(Secure Hashing Algorithm 2) 해싱 구현

hashing ; 해싱은 하나의 문자열을 원래의 것을 상징하는 더 짧은 길이의 값이나 키로 변환하는 것

암호용 해시 함수는 매핑된 해싱 값만을 알아가지고는 원래 입력 값을 알아내기 힘들다는 사실에 의해 사용될 수 있다.

func sha256(_ input: String) -> String {
    let inputData = Data(input.utf8)
    let hashedData = SHA256.hash(data: inputData)
    let hashString = hashedData.compactMap {
        return String(format: "%02x", $0)
    }.joined()
    
    return hashString
}

Delegate

인증에 성공하면 ASAuthorizationController는 app이 사용자 데이터를 키 체인에 저장하는 데 사용하는 함수를 호출

사용자 정보(이메일, 이름 등)는 초기 등록 시에만 ASAuthorizationAppleIDCredential로 전송되고 이후에는 userIdentifier만 전송된다.

func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization)

Credential

1. appleIDCredential

/// userIdentifier
let userIdentifier = appleIDCredential.user

/// A JSON Web Token (JWT) that securely communicates information about the user to the app.
let identityToken = appleIDCredential.identityToken

/// short-lived token as proof that it has authorization to interact with the server
let authorizationCode = appleIDCredential.authorizationCode

2. passwordCredential

기존 iCloud 키체인 자격 증명을 사용하여 로그인

let user = passwordCredential.user
let password = passwordCredential.password

GitHub

View Github