macOS 및 iOS에서 SSO 구성

macOS 및 iOS용 MSAL(Microsoft 인증 라이브러리)은 macOS/iOS 앱과 브라우저 간에 SSO(Single Sign-On)를 지원합니다. 이 문서에서는 다음 SSO 시나리오를 다룹니다.

이 유형의 SSO는 동일한 Apple Developer에서 배포하는 여러 앱 간에 작동합니다. 키 집합에서 다른 앱에서 작성한 새로 고침 토큰을 읽고 액세스 토큰을 자동으로 교환하여 자동 SSO(즉, 사용자에게 자격 증명을 묻는 메시지가 표시되지 않음)를 제공합니다.

Microsoft 모바일 디바이스가 Microsoft Entra ID 등록된 한 다른 공급업체의 애플리케이션 간에 SSO를 사용하도록 설정하는 broker라는 앱을 제공합니다. 이 유형의 SSO를 사용하려면 사용자의 디바이스에 broker 애플리케이션을 설치해야 합니다.

  • MSAL과 Safari 간 SSO

SSO는 ASWebAuthenticationSession 클래스를 통해 달성됩니다. 다른 앱 및 Safari 브라우저의 기존 로그인 상태를 사용합니다. 동일한 Apple Developer에서 배포하는 앱으로 제한되지는 않지만 일부 사용자 상호 작용이 필요합니다.

앱에서 기본 웹 보기를 사용하여 사용자를 로그인하는 경우 MSAL 기반 애플리케이션과 Safari 간에 자동 SSO가 표시됩니다. MSAL에서 지원하는 웹 보기에 대해 자세히 알아보려면 브라우저 및 WebView 사용자 지정을 방문하세요.

이 유형의 SSO는 현재 macOS에서 사용할 수 없습니다. macOS의 MSAL은 Safari에서 SSO를 지원하지 않는 WKWebView만 지원합니다.

메모

iOS는 로그인을 수행하기 위해 임시 브라우저를 사용하여 로그인한 직후에 세션 쿠키를 지웁니다. 이 브라우저는 세션 쿠키를 공유하지 않습니다. IOS에서 SSO가 작동하도록 하려면 영구 쿠키를 활용하려면 KMSI를 사용하도록 설정해야 합니다.

  • ADAL 및 MSAL macOS/iOS 앱 사이의 자동 SSO

MSAL Objective-C ADAL Objective-C 기반 앱을 사용하여 마이그레이션 및 SSO를 지원합니다. 앱은 동일한 Apple 개발자가 배포해야 합니다.

ADAL 및 MSAL 기반 앱 간의 앱 간 SSO에 대한 지침은 macOS 및 iOS의 ADAL 및 MSAL 앱 간의 SSO를 참조하세요.

앱 간 무중단 SSO

MSAL은 iOS 키 집합 액세스 그룹을 통한 SSO 공유를 지원합니다.

애플리케이션에서 SSO를 사용하도록 설정하려면 아래 자세히 설명된 다음 단계를 수행해야 합니다.

  1. 모든 애플리케이션이 동일한 클라이언트 ID 또는 애플리케이션 ID를 사용하는지 확인합니다.
  2. 키 집합을 공유할 수 있도록 모든 애플리케이션이 Apple에서 동일한 서명 인증서를 공유하는지 확인합니다.
  3. 각 애플리케이션에 대해 동일한 키 집합 자격을 요청합니다.
  4. 기본 키 집합과 다른 경우 사용하려는 공유 키 집합에 대해 MSAL SDK에 알릴 수 있습니다.

동일한 클라이언트 ID 및 애플리케이션 ID 사용

Microsoft ID 플랫폼 토큰을 공유할 수 있는 애플리케이션을 파악하려면 해당 애플리케이션이 동일한 클라이언트 ID 또는 애플리케이션 ID를 공유해야 합니다. 포털에서 첫 번째 애플리케이션을 등록할 때 제공된 고유 식별자입니다.

Microsoft ID 플랫폼이 동일한 애플리케이션 ID를 사용하는 앱들을 서로 구분하는 방식은 리디렉션 URI를 기준으로 하는 것입니다. 각 애플리케이션은 온보딩 포털에 여러 리디렉션 URI를 등록할 수 있습니다. 제품군의 각 앱에는 다른 리디렉션 URI가 있습니다. 다음은 그 예입니다.

App1 리디렉션 URI: msauth.com.contoso.mytestapp1://auth
App2 리디렉션 URI: msauth.com.contoso.mytestapp2://auth
App3 리디렉션 URI: msauth.com.contoso.mytestapp3://auth

리디렉션 URI 형식은 MSAL이 지원하는 형식과 호환되어야 하며 MSAL 리디렉션 URI 형식 요구 사항에 설명되어 있습니다.

애플리케이션 간에 키 집합 공유 설정

키 집합 공유를 사용하도록 설정하려면 Apple의 기능 추가 문서를 참조하세요. 중요한 것은 키 집합을 호출할 항목을 결정하고 SSO와 관련된 모든 애플리케이션에 해당 기능을 추가한다는 것입니다.

자격이 올바르게 설정되면 프로젝트 디렉터리에 다음 예제와 같은 내용이 포함된 파일이 표시됩니다 entitlements.plist .

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>keychain-access-groups</key>
    <array>
        <string>$(AppIdentifierPrefix)com.myapp.mytestapp</string>
        <string>$(AppIdentifierPrefix)com.myapp.mycache</string>
    </array>
</dict>
</plist>

새 키 집합 그룹 추가

프로젝트의 기능에 새 키체인 그룹을 추가합니다 . 키체인 그룹은 다음과 같아야 합니다.

  • com.microsoft.adalcache iOS에서
  • com.microsoft.identity.universalstorage macOS에서

키체인 예제

자세한 내용은 키 집합 그룹을 참조하세요.

애플리케이션 개체 구성

각 애플리케이션에서 키체인 권한을 사용하도록 설정하고 SSO를 사용할 준비가 되면 다음 예제와 같이 키체인 액세스 그룹으로 MSALPublicClientApplication를 구성합니다.

Objective-C:

NSError *error = nil;
MSALPublicClientApplicationConfig *configuration = [[MSALPublicClientApplicationConfig alloc] initWithClientId:@"<my-client-id>"];
configuration.cacheConfig.keychainSharingGroup = @"my.keychain.group";

MSALPublicClientApplication *application = [[MSALPublicClientApplication alloc] initWithConfiguration:configuration error:&error];

재빠르다:

let config = MSALPublicClientApplicationConfig(clientId: "<my-client-id>")
config.cacheConfig.keychainSharingGroup = "my.keychain.group"

do {
   let application = try MSALPublicClientApplication(configuration: config)
  // continue on with application
} catch let error as NSError {
  // handle error here
}

Warning

애플리케이션 간에 키 집합을 공유하는 경우 모든 애플리케이션은 애플리케이션에서 사용자 또는 모든 토큰을 삭제할 수 있습니다. 이는 백그라운드 작업을 수행하는 토큰을 사용하는 애플리케이션이 있는 경우 특히 영향을 줍니다. 키 집합을 공유한다는 것은 앱에서 Microsoft ID SDK 제거 작업을 사용할 때 매우 주의해야 한다는 것을 의미합니다.

이것으로 끝입니다. 이제 Microsoft ID SDK가 모든 애플리케이션에서 자격 증명을 공유합니다. 계정 목록은 애플리케이션 인스턴스 간에도 공유됩니다.

iOS에서 인증 브로커를 통한 SSO

MSAL은 Microsoft Authenticator 사용하여 조정된 인증을 지원합니다. Microsoft Authenticator 등록된 Microsoft Entra 디바이스에 대한 SSO를 제공하며 애플리케이션이 조건부 액세스 정책을 따르는 데도 도움이 됩니다.

다음 단계는 앱에 인증 브로커를 사용하여 SSO를 사용하도록 설정하는 방법입니다.

  1. 앱의 Info.plist에 애플리케이션에 대한 broker 호환 리디렉션 URI 형식을 등록합니다. 브로커와 호환되는 리디렉션 URI 형식은 msauth.<app.bundle.id>://auth입니다. '<app.bundle.id>'을 애플리케이션의 번들 ID로 대체합니다. 다음은 그 예입니다.

    <key>CFBundleURLSchemes</key>
    <array>
        <string>msauth.<app.bundle.id></string>
    </array>
    
  2. 앱의 Info.plist에서 LSApplicationQueriesSchemes 아래에 다음 스키마를 추가합니다.

    <key>LSApplicationQueriesSchemes</key>
    <array>
         <string>msauthv2</string>
         <string>msauthv3</string>
    </array>
    
  3. 콜백을 처리하려면 AppDelegate.m 파일에 다음을 추가합니다.

    Objective-C:

    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
    {
        return [MSALPublicClientApplication handleMSALResponse:url sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]];
    }
    

    재빠르다:

    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String)
    }
    

Xcode 11을 사용하는 경우 MSAL 콜백을 SceneDelegate 파일에 대신 배치해야 합니다. 이전 iOS와의 호환성을 위해 UISceneDelegate와 UIApplicationDelegate를 모두 지원하는 경우 MSAL 콜백을 두 파일에 모두 배치해야 합니다.

Objective-C:

 - (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
 {
     UIOpenURLContext *context = URLContexts.anyObject;
     NSURL *url = context.URL;
     NSString *sourceApplication = context.options.sourceApplication;

     [MSALPublicClientApplication handleMSALResponse:url sourceApplication:sourceApplication];
 }

재빠르다:

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {

        guard let urlContext = URLContexts.first else {
            return
        }

        let url = urlContext.url
        let sourceApp = urlContext.options.sourceApplication

        MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: sourceApp)
    }