애플 로그인1 - Sign in with Apple (Objective C)

애플 정책에 따라 앱에서 사용자의 기본 계정 설정을 타사 소셜 로그인 서비스 (페이스북 구글, 트위터 등) 사용하는 앱은 Apple 로그인 역시 동등하게 제공해야 합니다. 사용자의 기본 계정은 사용자 식별, 로그인, 앱의 기능 및 연결된 서비스에 접근하기 위한 목적으로 앱에 설정한 계정을 의미합니다.

 

애플 로그인 예제

애플에서 이제 Objective-C는 예제도 제공하지 않는군요. 애플 공식 예제에는 Swift만 제공되어있습니다. 

 

AuthenticationServices

Sign In with Apple 애플 로그인은 구현하기 위해서는 AuthenticationServices.Framework 를 추가해야 합니다. Xcode 11.3+부터 사용이 가능하며 iOS 13.0부터 적용이 가능합니다. 하위 버전이나 다른 플랫폼의 경우 웹(js)을 통해서 애플 로그인을 구현할 수 있다고 합니다. 추후에 적용을 할지는 아직 모르겠습니다. (Firebase를 이용하는 방법도 있다고 하네요.)

 

Capabilities 추가하기

이제 Xcode에서 Capabilities를 추가해야 합니다. Xcode에서 해당 앱 Target의 Signing & Capabilities를 눌러줍니다.

 

 

왼쪽 상단에 Capability 를 눌러서 Sign In with Apple 을 추가해 줍니다.

 

 

이렇게 추가를 하게 되면 .entitlements 파일이 추가가 됩니다. 해당 파일을 보면 com.apple.developer.applesignin 가 있는 걸 볼 수 있습니다. 해당 키가 앱에서 애플 로그인을 사용할 수 있는 권한입니다.

 

Sign In with Apple - Objective C

#import <AuthenticationServices/AuthenticationServices.h>

@interface ViewController : 
UIViewController<ASAuthorizationControllerDelegate,ASAuthorizationControllerPresentationContextProviding>

@end

먼저 AuthenticationServices.h 를 import 해 줍니다. (샘플 코드)

 

그리고 필요한 프로토콜이 2개가 있습니다.

  • ASAuthorizationControllerDelegat
  • ASAuthorizationControllerPresentationContextProviding

 

 

이제 애플 로그인을 위한 버튼을 만들어야 합니다. 저는 게임 UI를 사용해서 직접 버튼을 만들어 테스트하지는 않았는데요. 예제로 만들어 보았습니다. 

 

ASAuthorizationAppleIDButton *appleIDButton = [ASAuthorizationAppleIDButton new];
[self.view addSubview:appleIDButton];
[appleIDButton addTarget:self action:@selector(handleAuthrization:) forControlEvents:UIControlEventTouchUpInside];

애플에서 제공해주는 버튼이 있습니다. 가이드라인이 적용된 버튼이기 때문에 ASAuthorizationAppleIDButton 을 이용하여서 만들어주면 됩니다. 

 

애플 로그인 요청

- (void)handleAuthrization:(UIButton *)sender {
ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
        
ASAuthorizationAppleIDRequest *request = [appleIDProvider createRequest];
request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
        
ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];

controller.delegate = self;
controller.presentationContextProvider = self;
[controller performRequests];               
}

버튼 액션으로 실행될 함수입니다. 애플 로그인을 요청하기 위해서는 ASAuthorizationAppleIDProvider 이 필요합니다. Apple ID를 기반으로 사용자를 인증하기 위한 요청을 생성하는 메커니즘이라고 설명되어있네요. 요청을 할 때에 이름과 이메일을 요구했습니다. ASAuthorizationAppleIDRequest 를 통해 요구할 수 있습니다. 

 

ASAuthorizationControllerdelegatepresentationContextProvider 를 세팅해줍니다. 앞에서 프로토콜 사용을 위해서 정의해두었습니다.

 

@protocol ASAuthorizationControllerDelegate <NSObject>
@optional
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization 

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error  
@end

애플 로그인을 요청하게 되면 딜리게이트 호출을 받을 수 있도록 함수를 정의해줍시다. 정상적으로 애플로그인이 되었을 때와 비정상적으로 에러가 발생했을 때에 호출받을 수 있습니다.

 

@protocol ASAuthorizationControllerPresentationContextProviding <NSObject>
@required
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller;
@end

context창을 어디에 띄울지를 물어보는 거네요. 이제 코드를 정의해 봅시다.

 

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error {

    switch (error.code) {
        case ASAuthorizationErrorCanceled:
            break;
        case ASAuthorizationErrorFailed:
            break;
        case ASAuthorizationErrorInvalidResponse:
            break;
        case ASAuthorizationErrorNotHandled:
            break;
        case ASAuthorizationErrorUnknown:
            break;
    }
}

로그인 시도 시 에러가 발생하게 되면 해당 메서드를 통해서 호출받을 수 있습니다. 

 

 - (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller {
    return self.view.window;
}

presentation이 될 수 있도록 해줍시다.

 

 

좌측은 최초 로그인을 시도했을 때입니다. 이름과 이메일을 요청했었죠. 오른쪽은 앱에 로그인을 성공하고 하고 나서 다시 시도할 경우입니다. 

 

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization {

    if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]])
    {
        ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
        NSString *user = appleIDCredential.user;
        NSString *email = appleIDCredential.email;        
        NSData *identityToken = appleIDCredential.identityToken;
        NSString* accessToken = [[NSString alloc] initWithData:identityToken
        encoding:NSUTF8StringEncoding];
            
        NSLog(@"ASAuthorizationAppleIDCredential.credential.user:%@", user);
        NSLog(@"ASAuthorizationAppleIDCredential.credential.email:%@", email);
        NSLog(@"ASAuthorizationAppleIDCredential.credential.idToken:%@", accessToken);

    }
    else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]])
    {
        ASPasswordCredential *passwordCredential = authorization.credential;
        NSString *user = passwordCredential.user;
        NSString *password = passwordCredential.password;

        NSLog(@"ASPasswordCredential.credential.user:%@", user);
        NSLog(@"ASPasswordCredential.credential.password:%@", password);
    }
    else
    {
        NSLog(@"APPLE LOGIN FAILED");
    }
}

먼저 정상적으로 애플로그인이 성공했을 호출받는 메서드입니다. 여기서 정상 로그인이 되었을 때에 데이터를 확인할 수 있습니다. 유효하게 사용할 수 있는 데이터로는 user, email, identityToken 이 있어요. 토큰은 서버에서 확인 할 때에 사용을 하면 됩니다.

 

 

email 정보의 경우 최초 로그인이 되었을 때만 값을 받을 수 있습니다. user 의 경우 고유값으로 현재 로그인 상태를 알 수 있는 값으로 사용할 수 있습니다. identityToken 의 경우 너무 길어서 사진은 생략할게요. 이메일을 숨기게 하니 이렇게 애플에서 변경하여 잘 내려 오네요.

 

여기서 잘 모르겠는 부분이 ASPasswordCredential 인데요. 어떤방식으로 로그인을 했을때에 호출이 되는지 잘 모르겠습니다. 테스트 방식을 모르겠습니다. 사용자의 기존 비밀번호 자격 증명을 통해서 로그인이 된거 같은데요. 좀 더 테스트를 해봐야 알 듯합니다.

 

로그인 확인

ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
[appleIDProvider getCredentialStateForUserID:@"userID" completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) {
	switch (credentialState) {
    	case ASAuthorizationAppleIDProviderCredentialRevoked:
            break;
        case ASAuthorizationAppleIDProviderCredentialAuthorized:
            break;
        case ASAuthorizationAppleIDProviderCredentialNotFound:
            break;
        case ASAuthorizationAppleIDProviderCredentialTransferred:
            break;
}
}];            

이제 애플로그인으로 받은 user 값을 통해서 현재 앱에 로그인 상태를 확인 할 수 있습니다. ASAuthorizationAppleIDProviderCredentialAuthorized 상태가 되어야지 정상정인 로그인 상태입니다. 시뮬에서는 확인이 안되었습니다. 실제 디바이스로 해야 로그인 상태를 확인 할 수 있습니다.

 

Identifier, Key 발급

프로젝트에 적용하기 전에 Apple Developer Account의 Identifier, Key를 발급받아야 합니다. 그런데 여기서 중요한 점이 있습니다. 개발 환경이 enterprise inhouse였는데요. inhouse Capabilities에는 Sign In with Apple이 없습니다. 그런데 또 시뮬에서는 로그인 호출시 제대로된 값 확인이 되지 않았어요. 매우 난감했습니다... 서비스하고있는 앱이라 저는 권한이 없어 직접 인증서 갱신을 해보지는 못했습니다.

 

Sign In with Apple의 추가내용은 정리해서 또 올리도록 하겠습니다. 

 

그리드형(광고전용)

이 글을 공유합시다

facebook twitter googleplus kakaoTalk kakaostory naver band

댓글

Designed by JB FACTORY