この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

Newer Version Available

This content describes an older version of this product. View Latest

LoginDiscoveryHandler インターフェース

Salesforce では、ユーザ名とパスワード以外の確認方法に基づくユーザのログイン機能が提供されます。たとえば、メール、電話番号、または別の ID (統合 ID やデバイス識別子など) を使用してログインするようにユーザに要求できます。

名前空間

Auth

使用方法

インタビューベースのログイン用の Auth.LoginDiscoveryHandler を実装します。このハンドラは、入力された ID からユーザを検索し、Site.passwordlessLogin をコールして、使用するログイン情報 (メール、SMS など) を決定できます。または、ハンドラはユーザをログイン用のサードパーティ ID プロバイダにリダイレクトできます。このハンドラを使用した場合、ログインページにパスワード項目は表示されません。ただし、Site.passwordlessLogin を使用して、パスワードを要求できます。

ユーザの観点では、ユーザはログイン画面で ID を入力します。次に、PIN またはパスワードを入力してログインを完了します。または、SSO が有効になっている場合、ユーザはログインをスキップします。

例については、「LoginDiscoveryHandler の実装例」を参照してください。詳細は、『Salesforce External Identity Implementation Guide (Salesforce External Identity 実装ガイド)』を参照してください。

LoginDiscoveryHandler メソッド

LoginDiscoveryHandler のメソッドは次のようになります。

login(identifier, startUrl, requestAttributes)

メールや電話番���などの識別子が指定された外部ユーザのログインを行います。成功した場合、開始 URL で指定されたコミュニティページにユーザをリダイレクトします。

署名

public System.PageReference login(String identifier, String startUrl, Map<String,String>requestAttributes)

パラメータ

identifier
型: String
ログイン画面で外部ユーザが入力した識別子 (メールアドレスや電話番号など)。
startUrl
型: String
外部ユーザが要求したコミュニティページへのパス。ログインが成功すると、ユーザはこの場所にリダイレクトされます。
requestAttributes
型: Map<String,String>
ログイン要求に関するさまざまなデータ (ユーザエージェント、IP アドレス、デバイス識別子、または他の HTTP ヘッダーなど)。ログインページにアクセスしたときにユーザのブラウザ状態に基づいてシステムによって提供されます。

戻り値

型: System.PageReference

ユーザがリダイレクトされるページの URL。

LoginDiscoveryHandler の実装例

この Apex コード例は Auth.LoginDiscoveryHandler インターフェースを実装します。ログインページで提供された ID に応じて、ログインしているユーザのメールまたは電話番号が検証済みかどうかをチェックします。検証済みの場合 (Auth.VerificationMethod.EMAIL または Auth.VerificationMethod.SMS)、ID (ユーザのメールアドレスまたはモバイルデバイス) にチャレンジを送信します。検証ページでユーザがコードを正しく入力すると、ユーザは開始 URL で指定されたコミュニティページにリダイレクトされます。ユーザが検証されない場合、ユーザはログインのためのパスワードを入力する必要があります。

discoveryResult 関数は Site.passwordlessLogin メソッドをコールし、指定された検証方法でユーザをログインします。getSsoRedirect 関数は、ユーザが SAML または認証プロバイダを使用してログインする必要があるかどうかを参照します。実装に固有のロジックを追���して、この参照方法を操作します。

1global class AutocreatedDiscLoginHandler implements Auth.LoginDiscoveryHandler {
2
3global PageReference login(String identifier, String startUrl, Map<String, String> requestAttributes) {
4    if (identifier != null && isValidEmail(identifier)) {
5        // Search for user by email 
6        List<User> users = [SELECT Id FROM User WHERE Email = :identifier AND IsActive = TRUE];
7        if (!users.isEmpty() && users.size() == 1) {
8            // User must have verified email before using this verification method. We cannot send message to unverified email. 
9            // You can check if the user has email verified bit on and add the password verification method as fallback.
10            List<TwoFactorMethodsInfo> verifiedInfo = [SELECT HasUserVerifiedEmailAddress FROM TwoFactorMethodsInfo WHERE UserId = :users[0].Id];
11            if (!verifiedInfo.isEmpty() && verifiedInfo[0].HasUserVerifiedEmailAddress == true) {
12                // Use email verification method if the user's email is verified.
13                return discoveryResult(users[0], Auth.VerificationMethod.EMAIL, startUrl, null);
14            } else {
15                // Use password verification method as fallback if the user's email is unverified.
16                return discoveryResult(users[0], Auth.VerificationMethod.PASSWORD, startUrl, null);
17            }
18        } else {
19            throw new Auth.LoginDiscoveryException('No unique user found. User count=' + users.size());
20        }
21    }
22    if (identifier != null) {
23        String formattedSms = getFormattedSms(identifier);
24        if (formattedSms != null) {
25            // Search for user by SMS 
26            List<User> users = [SELECT Id FROM User WHERE MobilePhone = :formattedSms AND IsActive = TRUE];
27            if (!users.isEmpty() && users.size() == 1) {
28                // User must have verified SMS before using this verification method. We cannot send message to unverified mobile number. 
29                // You can check if the user has mobile verified bit on or add the password verification method as fallback.
30                List<TwoFactorMethodsInfo> verifiedInfo = [SELECT HasUserVerifiedMobileNumber FROM TwoFactorMethodsInfo WHERE UserId = :users[0].Id];
31                if (!verifiedInfo.isEmpty() && verifiedInfo[0].HasUserVerifiedMobileNumber == true) {
32                    // Use SMS verification method if the user's mobile number is verified.
33                    return discoveryResult(users[0], Auth.VerificationMethod.SMS, startUrl, null);
34                } else {
35                    // Use password verification method as fallback if the user's mobile number is unverified.
36                    return discoveryResult(users[0], Auth.VerificationMethod.PASSWORD, startUrl, null);
37                }
38            } else {
39                throw new Auth.LoginDiscoveryException('No unique user found. User count=' + users.size());
40            }
41        }
42    }
43    if (identifier != null) {
44        // You can customize the code to find user via other attributes, such as SSN or Federation ID
45    }
46    throw new Auth.LoginDiscoveryException('Invalid Identifier');
47}
48
49private boolean isValidEmail(String identifier) {
50    String emailRegex = '^[a-zA-Z0-9._|\\\\%#~`=?&/$^*!}{+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$';
51    // source: http://www.regular-expressions.info/email.html 
52    Pattern EmailPattern = Pattern.compile(emailRegex);
53    Matcher EmailMatcher = EmailPattern.matcher(identifier);
54    if (EmailMatcher.matches()) { return true; }
55    else { return false; }
56}
57
58private String getFormattedSms(String identifier) {
59    // Accept SMS input formats with 1 or 2 digits country code, 3 digits area code and 7 digits number
60    // You can customize the SMS regex to allow different formats
61    String smsRegex = '^(\\+?\\d{1,2}?[\\s-])?(\\(?\\d{3}\\)?[\\s-]?\\d{3}[\\s-]?\\d{4})$';
62    Pattern smsPattern = Pattern.compile(smsRegex);
63    Matcher smsMatcher = SmsPattern.matcher(identifier);
64    if (smsMatcher.matches()) {
65        try {
66            // Format user input into the verified SMS format '+xx xxxxxxxxxx' before DB lookup
67            // Append US country code +1 by default if no country code is provided
68            String countryCode = smsMatcher.group(1) == null ? '+1' : smsMatcher.group(1);
69            return System.UserManagement.formatPhoneNumber(countryCode, smsMatcher.group(2));
70        } catch(System.InvalidParameterValueException e) {
71            return null;
72        }
73    } else { return null; }
74}
75
76private PageReference getSsoRedirect(User user, String startUrl, Map<String, String> requestAttributes) {
77    // You can look up if the user should log in with SAML or an Auth Provider and return the URL to initialize SSO.
78    return null;
79}
80
81private PageReference discoveryResult(User user, Auth.VerificationMethod method, String startUrl, Map<String, String> requestAttributes) {
82    PageReference ssoRedirect = getSsoRedirect(user, startUrl, requestAttributes);
83    if (ssoRedirect != null) {
84        return ssoRedirect;
85    } else {
86        if (method != null) {
87            List<Auth.VerificationMethod> methods = new List<Auth.VerificationMethod>();
88            methods.add(method);
89            PageReference pwdlessRedirect = Site.passwordlessLogin(user.Id, methods, startUrl);
90            if (pwdlessRedirect != null) {
91                return pwdlessRedirect;
92            } else {
93                throw new Auth.LoginDiscoveryException('No Passwordless Login redirect URL returned for verification method: ' + method);
94            }
95        } else {
96            throw new Auth.LoginDiscoveryException('No method found');
97        }
98    }
99}
100}