Configuring Email OTP¶
This section provides the instructions to configure multi-factor authentication (MFA) using Email One Time Password (Email OTP) in WSO2 Identity Server (WSO2 IS). The Email OTP enables a one-time password (OTP) to be used at the second step of MFA.
Info
For information on MFA concepts, see About MFA.
Follow the instructions in the sections below to configure MFA using Email OTP:
Deploying the sample application¶
In this guide we will be using SAML pickup-dispatch as a sample application to which we will be enabling MFA for sign-in. To deploy the pickup-dispatch sample application, follow the steps in Deploying the SAML2 Pickup-Dispatch Sample App.
Configure the email OTP provider¶
You can use WSO2 Identity Server as the email OTP provider or you can configure Gmail or SendGrid as the email OTP provider using Gmail or SendGrid APIs. Follow the instructions in one of Option1 or Option2 to set up the email OTP provider.
Option1: Configure WSO2 IS as the email OTP provider¶
Follow the steps below to configure WSO2 IS to send emails once the Email OTP is enabled.
-
Enable the email sending configurations of the WSO2 Identity Server as explained here.
Tip
The email template used to send this email notification is the EmailOTP template.
You can edit and customize the email template. For more information on how to do this, see Customizing Automated Emails.
-
Add the following configuration to the
deployment.toml
file in the<IS_HOME>/repository/conf/
directory.[authentication.authenticator.email_otp] name ="EmailOTP" enable=true [authentication.authenticator.email_otp.parameters] EMAILOTPAuthenticationEndpointURL = "https://localhost:9443/emailotpauthenticationendpoint/emailotp.jsp" EmailOTPAuthenticationEndpointErrorPage = "https://localhost:9443/emailotpauthenticationendpoint/emailotpError.jsp" EmailAddressRequestPage = "https://localhost:9443/emailotpauthenticationendpoint/emailAddress.jsp" usecase = "local" secondaryUserstore = "primary" EMAILOTPMandatory = false sendOTPToFederatedEmailAttribute = false federatedEmailAttributeKey = "email" EmailOTPEnableByUserClaim = true CaptureAndUpdateEmailAddress = true showEmailAddressInUI = true useEventHandlerBasedEmailSender = true emailAddressRegex = '(?<=.{1}).(?=.*@)' tokenExpirationTime = 300000
Click to view the parameter definitions
Parameter Description Sample Values usecase
This parameter defines how the email ID will be retrieved. local
: This is the default value and is based on the federated username. You must set the federated username in the local userstore . The federated username must be the same as the local username.assocication
: The federated username must be associated with the local account in advance in the My Account. The local username is retrieved from the association. To associate the user, log into the My Account and go to Associated Account by clicking View details.subjectUri
: When configuring the federated authenticator, select the attribute in the subject identifier under the service provider section in UI, this is used as the username of theEmailOTP
authenticator.-
userAttribute
: The name of the federated authenticator's user attribute. That is the local username that is contained in a federated user's attribute. When using this, add the following parameter under the[authentication.authenticator.email_otp.parameters]
section in thedeployment.toml
file and put the value, e.g., email and screen_name, id.[authentication.authenticator.email_otp.parameters] userAttribute = "email"
If you use OpenID Connect supported authenticators such as LinkedIn and Foursquare or in the case of multiple social login options as the first step and EmailOTP as second step, you need to add similar configuration for the specific authenticator in the
deployment.toml
file.Click here to view examples
Facebook
[authentication.authenticator.facebook.parameters] EmailOTP-userAttribute = "email" federatedEmailAttributeKey = "email"
Foursquare
Likewise, you can add the Authenticator Config for Amazon, Google, Twitter, and Instagram with the relevant values.[[authentication.custom_authenticator]] name= "Foursquare" [authentication.custom_authenticator.parameters] EmailOTP-userAttribute = "http://wso2.org/foursquare/claims/email" federatedEmailAttributeKey = "http://wso2.org/foursquare/claims/email"
local
association
userAttribute
subjectUri
secondaryUserstore
You can define multiple user stores per tenant as comma separated values.
Example:
secondaryUserstore = "jdbc, abc, xyz"
Tip
The user store configurations are maintained per tenant:
- If you use a super tenant, set all the parameter values into the
file./repository/conf/deployment.toml - If you use a tenant,
- Upload the XML file (
) into a specific registry location (/repository/conf/identity/application-authentication.xml /_system/governance/EmailOTP
). - Create the collection named
EmailOTP
, add the resource and upload theapplication-authentication.xml
file into the registry. - While doing the authentication,the sysetm first checks whether there is an XML file uploaded to the registry. If that is so, it reads it from the registry but does not take the local file. If there is no file in the registry, then it only takes the property values from the local file.
- You can use the registry or local file to get the property values.
- Upload the XML file (
EMAILOTPMandatory
Thisparmeterdefineswhtherthe EmailOTP is enforced as the second step of the 2FA/MFA or not.
- If the user is not found in the active directory where the parameter is set to
true
, the OTP is directly sent to the email address defined in the claims set. - If the user is not found in the active directory where the parameter is set to
false
, the authentication flow terminates at the first step of the 2FA/MFA.
true
false
sendOTPToFederatedEmailAttribute
When the
EMAILOTPMandatory
and this parameter are set to true and the user is not found in the active directory, the OTPissetn to the mail defined in the federated authenticator claim.When the
EMAILOTPMandatory
is set tofalse
, an error page gets displayed.When the
EMAILOTPMandatory
is set to false and the user is not found in the active directory, the authentication mechanism terminates at the first step of the 2FA/MFA. This parameter is not required in such a scenario.true
false
federatedEmailAttributeKey
This parameter identifies the email attribute of the federated authenticator,
e.g. Foursquare. Set this parameter if thesendOTPToFederatedEmailAttribute
is set totrue
. Example:http://wso2.org/foursquare/claims/email
EmailOTPEnableByUserClaim
This parameter enables the user to override the functionality defined at the
EMAILOTPMandatory
parameter.- If this parameter and the
EMAILOTPMandatory
parameters are set totrue
, the user can either enable or disable the EmailOTP functionality. - If this parameter is set to
false
where theEMAILOTPMandatory
parameter is set totrue
, the user gets redirected to an error page. - If this parameter and the
EMAILOTPMandatory
parameters are set tofalse
, the authentication flow terminates at the first step of the 2FA/MFA. - If the user is not available in the active directory
true
false
CaptureAndUpdateEmailAddress
This parameter enables the user to update the email address that is used to send the OTP, at the first login where the email address is not previously set. true
false
EmailAddressRequestPage
This parameter enables to display a page that requests for an email address where
- The user has not registered an email address.
- Sending OTP is defined as the second step of 2FA/MFA.
- The
CaptureAndUpdateEmailAddress
parameter is set totrue
.
Example:
https://localhost:9443/emailotpauthenticationendpoint/emailAddress.jsp
showEmailAddressInUI
This parameter enables to display the email address to which the OTP is sent to on the UI. true
false
emailAddressRegex
When showEmailAddressInUI
is enabled, it provides the capability to define the way the email address should be displayed in the UI. This can be configured with a proper regex pattern as required.(?<=.{1}).(?=.@)
:t***@mail.com
(?<=.)^@|(?:(?<=@.)|(?!)\G(?=[@]$)).(?=.*\.)
:t***@m***.com
tokenExpirationTime
This parameter helps to define a custom Email OTP expiry time. The default expiration time is 300000 milliseconds. 300000
Option2: Configure Gmail as the email OTP provider¶
Follow the steps below to send the One Time Password (OTP) using Gmail APIs or using SendGrid."
- Create a Google account at https://gmail.com.
- Go to https://console.developers.google.com and click ENABLE APIS AND SERVICES.
- Search for Gmail API and click on it.
-
Click Enable to enable the Gmail APIs.
Why is this needed?
If you do not enable the Gmail APIs, you will run into a 401 error when trying out step13.
-
Click Credentials and click Create to create a new project.
-
Click Credentials and click the Create credentials drop-down.
-
Select OAuth client ID option.
-
Click Configure consent screen.
-
Enter the Product name that needs to be shown to users, enter values to any other fields you prefer to update, and click Save.
-
Select the Web application option.
Enter
https://localhost:9443/commonauth
as the Authorize redirect URIs and click Create.The
client ID
and theclient secret
are displayed.
Copy the client ID and secret and keep it in a safe place as you will require it for the next step.
-
Copy the URL below and replace the
<CLIENT_ID>
placeholder tag with the generatedClient ID
. This is required to generate the authorization code.https://accounts.google.com/o/oauth2/auth?redirect_uri=https%3A%2F%2Flocalhost%3A9443%2Fcommonauth&response_type=code&client_id=<CLIENT_ID>&scope=http%3A%2F%2Fmail.google.com&approval_prompt=force&access_type=offline
https://accounts.google.com/o/oauth2/auth?redirect_uri=https%3A%2F%2Flocalhost%3A9443%2Fcommonauth&response_type=code&client_id=854665841399-l13g81ri4q98elpen1i1uhsdjulhp7ha.apps.googleusercontent.com&scope=http%3A%2F%2Fmail.google.com&approval_prompt=force&access_type=offline
-
Paste the updated URL into your browser.
- Select the preferred Gmail account with which you wish to proceed.
- Click Allow.
-
Obtain the
authorization code
using a SAML tracer on your browser.
-
To generate the access token, copy the following cURL command and replace the following place holders:
<CLIENT-ID>
: Replace this with theclient ID
obtained in Step 10 above.<CLIENT_SECRET>
: Replace this with theclient secret
obtained in Step 10 above.<AUTHORIZATION_CODE>
: Replace this with the authorization code obtained in Step 12 above.
curl -v -X POST --basic -u <CLIENT-ID>:<CLIENT_SECRET> -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -k -d "grant_type=authorization_code&code=<AUTHORIZATION_CODE>&redirect_uri=https://localhost:9443/commonauth" https://www.googleapis.com/oauth2/v3/token
curl -v -X POST --basic -u 854665841399-l13g81ri4q98elpen1i1uhsdjulhp7ha.apps.googleusercontent.com:MK3h4fhSUT-aCTtSquMB3Vll -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -k -d "grant_type=authorization_code&code=4/KEDlA2KjGtib4KlyzaKzVNuDfvAmFZ10T82usT-6llY#&redirect_uri=https://localhost:9443/commonauth" https://www.googleapis.com/oauth2/v3/token
> POST /oauth2/v3/token HTTP/1.1 > Host: www.googleapis.com > Authorization: Basic OTk3NDE2ODczOTUwLWY4Y2N1YnJobW1ramdkYXNkNnZkZ2tzOGxoaWExcnRhLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tOkJkNlBoY3ZVWXFrM1BhdnA4ZjBZcUQtMw== > User-Agent: curl/7.54.0 > Accept: */* > Content-Type: application/x-www-form-urlencoded;charset=UTF-8 > Content-Length: 127 > < HTTP/1.1 200 OK < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Pragma: no-cache < Expires: Mon, 01 Jan 1990 00:00:00 GMT < Date: Wed, 10 Jan 2018 08:29:57 GMT < Vary: X-Origin < Content-Type: application/json; charset=UTF-8 < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < X-XSS-Protection: 1; mode=block < Server: GSE < Alt-Svc: hq=":443"; ma=2592000; quic=51303431; quic=51303339; quic=51303338; quic=51303337; quic=51303335,quic=":443"; ma=2592000; v="41,39,38,37,35" < Accept-Ranges: none < Vary: Origin,Accept-Encoding < Transfer-Encoding: chunked < { "access_token": "ya29.Gls-BbTUseE2f-Lrc9q0QtdlvIoYFTg2zkYPsXHwgob4pHAFlE66GMgJjwTHT9eHfivhVcATROzU8FaUgt0wVL1sz-7IsC2Slfpdm6i3uFcurNTFbTlABk3jKJ--", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "1/8pMBx_lrUyitknmGzzH-yOcvoPIZ1OqhPeWvcYJOd0U" }
Paste the updated cURL command in your terminal to generate the OAuth2 access token, token validity period, and the refresh token.
-
Update the following configurations in the
<IS_HOME>/repository/conf/deployment.toml
file.Tip
- If you need to send the content in a payload, you can introduce a property in a format \<API> Payload and define the value. Similarly, you can define the Form Data.FormdataforSendgridAPIisgivenasan example.
- You can use \<API> URLParams, \<API>AuthTokenType, \<API>Failure and \<API>TokenEndpoint property formats to specify the URL parameters, Authorization token type, Message to identify failure and Endpoint to get access token from refresh token respectively.
- Value of \<API> URLParams should be like; api_user=\<API_USER>&api_key=\<API_KEY>&data=\<DATA>&list\<LIST>
Property Description GmailClientId
Enter the Client ID you got in step 10 .
Example:501390351749-ftjrp3ld9da4ohd1rulogejscpln646s.apps.googleusercontent.com
GmailClientSecret
Enter the client secret you got in step 10 .
Example:dj4st7_m3AclenZR1weFNo1V
SendgridAPIKey
This property is only required if you are using the Sengrid method. Since you are using Gmail APIs, keep the default value. GmailRefreshToken
Enter the refresh token that you got as the response in step 13 . Example: 1/YgNiepY107SyzJdgpynmf-eMYP4qYTPNG_L73MXfcbv
GmailEmailEndpoint
Enter your username of your Gmail account in place of the [userId]
place holder. Example:https://www.googleapis.com/gmail/v1/users/[email protected]/messages/send
SendgridEmailEndpoint
This property is only required if you are using the Sengrid method. Since you are using Gmail APIs, keep the default value. accessTokenRequiredAPIs
Use the default value.
apiKeyHeaderRequiredAPIs
This property is only required if you are using the Sengrid method. Since you are using Gmail APIs, keep the default value.
SendgridFormData=to
This property is only required if you are using the Sengrid method. Since you are using Gmail APIs, keep the default value. SendgridURLParams
This property is only required if you are using the Sengrid method. Since you are using Gmail APIs, keep the default value. GmailAuthTokenType
Use the default value. GmailTokenEndpoint
Use the the deafult value. SendgridAuthTokenType
This property is only required if you are using the Sengrid method. Since you are using Gmail APIs, keep the default value. Sample configuration:
[authentication.authenticator.email_otp] name = "EmailOTP" enable= true [authentication.authenticator.email_otp.parameters] GmailClientId = "<gmail_client_id>" GmailClientSecret = "<gmail_client_secret>" GmailRefreshToken = "<refresh_token>" GmailEmailEndpoint = "https://www.googleapis.com/gmail/v1/users/<mail_address>/messages/send" accessTokenRequiredAPIs = "Gmail" GmailAuthTokenType = "Bearer" GmailTokenEndpoint = "https://www.googleapis.com/oauth2/v3/token"
Configure the Identity Provider¶
Follow the steps below to add an identity provider:
-
Click Add under Main > Identity > Identity Providers.
-
Provide a suitable name for the identity provider.
-
Expand the EmailOTPAuthenticator Configuration under Federated Authenticators.
-
Select the Enable and Default check boxes(If you are using Gmail or Sendgrid as the email OTP provider, provide values for Email API and Email fields as well).
-
Click Register.
You have now added the identity provider.
Configure the Service Provider¶
In the Deploying the sample application section you have configured a service provider to register the "Pickup-dispatch" as an application in WSO2 Identity Server. Follow the steps below to modify the same service provider in order to configure Email OTP as second authentication step.
-
Return to the Management Console home screen.
-
Click List under Main > Identity > Service Providers and locate the above created service provider and click Edit.
-
Go to Claim Configuration and select the http://wso2.org/claims/emailaddress claim.
-
Go to Local and Outbound Authentication Configuration section.
-
Select the Advanced configuration radio button option.
-
Creating the first authentication step:
-
Click Add Authentication Step.
-
Click Add Authenticator that is under Local Authenticators of Step 1 to add the basic authentication as the first step.
Adding basic authentication as a first step ensures that the first step of authentication will be done using the user's credentials that are configured with the WSO2 Identity Server.Note
Use subject identifier from this step and Use attributes from this step will be selected by default. If not, make sure to select the two checkboxes.
-
-
Creating the second authentication step:
-
Click Add Authentication Step.
-
Click Add Authenticator that is under Federated Authenticators of Step 2 to add the EMAIL OTP identity provider you created as the second step.
EMAIL OTP is a second step that adds another layer of authentication and security.
-
-
-
Click Update.
You have now added and configured the service provider.
Note
For more information on service provider configuration, see Configuring SAML2 Web Single Sign-On.
Update the email address of the user¶
Follow the steps given below to update the user's email address.
- Return to the WSO2 Identity Server Management Console home screen.
- Click List under Add under Main > Identity > Users and Roles.
- Click Users.
- Click User Profile under Admin.
- Update the email address.
- Click Update.
Configure the user claims¶
Follow the steps below to map the user claims:
-
Click List under Main > Identity > Claims.
-
Click http://wso2.org/claims.
-
Click Edit in Disable EmailOTP.
-
Select Supported by Default and click Update.
Tip
To disable this claim for the admin user, navigate to Users and Roles > List and click Users. Click on the User Profile link corresponding to admin account and enter
true
as the value for the Disable EmailOTP field. This will disable the second factor authentication for the admin user.
Try it out¶
-
Navigate to http://localhost.com:8080/saml2-web-app-pickup-dispatch.com/ on your browser and click Login.
-
You will be redirected to the login page of WSO2 Identity Server. Log in using your WSO2 Identity Server credentials (admin/admin).
-
You will receive a token to your email account. Enter the code to authenticate.
-
If the authentication is successful, you will be redirected to the home page.
What's next?¶
- Want to see more federated authenticators? See, Configuring Federated Authentication.
- Try out enabling multi factor authentication using the SMSOTP feature of WSO2 IS.