Skip to contentSkip to navigationSkip to topbar
On this page

Account Verification with Authy, Java and Servlets


(warning)

Warning

As of November 2022, Twilio no longer provides support for Authy SMS/Voice-only customers. Customers who were also using Authy TOTP or Push prior to March 1, 2023 are still supported. The Authy API is now closed to new customers and will be fully deprecated in the future.

For new development, we encourage you to use the Verify v2 API.

Existing customers will not be impacted at this time until Authy API has reached End of Life. For more information about migration, see Migrating from Authy to Verify for SMS(link takes you to an external page).

Ready to implement user account verification in your application? Here's how it works at a high level:

  1. The users begin the registration process by entering their data, including a phone number, into a signup form.
  2. The authentication system sends a one-time password to the user's mobile phone to verify the possession of that phone number.
  3. The user enters the one-time password into a form before completing registration.
  4. The user opens a success page and receives an SMS indicating that their account has been created.

Building Blocks

building-blocks page anchor

To get this done, you'll be working with the following Twilio-powered APIs:

Authy REST API

Twilio REST API

  • Messages Resource: We will use Twilio directly to send our user a confirmation message after they create an account.

Deployment descriptor

deployment-descriptor page anchor
1
<?xml version="1.0" encoding="UTF-8"?>
2
3
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
4
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
6
version="3.0">
7
<welcome-file-list>
8
<welcome-file>home.html</welcome-file>
9
</welcome-file-list>
10
<servlet>
11
<servlet-name>registration</servlet-name>
12
<servlet-class>com.twilio.verification.servlet.RegistrationServlet</servlet-class>
13
</servlet>
14
<servlet>
15
<servlet-name>verify-code</servlet-name>
16
<servlet-class>com.twilio.verification.servlet.VerifyCodeServlet</servlet-class>
17
</servlet>
18
<servlet>
19
<servlet-name>account</servlet-name>
20
<servlet-class>com.twilio.verification.servlet.AccountServlet</servlet-class>
21
</servlet>
22
<servlet>
23
<servlet-name>resend-token</servlet-name>
24
<servlet-class>com.twilio.verification.servlet.ResendTokenServlet</servlet-class>
25
</servlet>
26
27
<servlet-mapping>
28
<servlet-name>registration</servlet-name>
29
<url-pattern>/registration</url-pattern>
30
</servlet-mapping>
31
<servlet-mapping>
32
<servlet-name>verify-code</servlet-name>
33
<url-pattern>/verify-code</url-pattern>
34
</servlet-mapping>
35
<servlet-mapping>
36
<servlet-name>account</servlet-name>
37
<url-pattern>/account</url-pattern>
38
</servlet-mapping>
39
<servlet-mapping>
40
<servlet-name>resend-token</servlet-name>
41
<url-pattern>/resend-token</url-pattern>
42
</servlet-mapping>
43
44
<filter>
45
<filter-name>authentication</filter-name>
46
<filter-class>com.twilio.verification.filter.AuthenticationFilter</filter-class>
47
</filter>
48
49
<filter-mapping>
50
<filter-name>authentication</filter-name>
51
<url-pattern>/account</url-pattern>
52
<url-pattern>/verify-code</url-pattern>
53
<url-pattern>/resend-token</url-pattern>
54
</filter-mapping>
55
56
<filter>
57
<filter-name>TeeFilter</filter-name>
58
<filter-class>ch.qos.logback.access.servlet.TeeFilter</filter-class>
59
</filter>
60
61
<filter-mapping>
62
<filter-name>TeeFilter</filter-name>
63
<url-pattern>/*</url-pattern>
64
</filter-mapping>
65
66
<filter>
67
<filter-name>LoggingFilter</filter-name>
68
<filter-class>com.twilio.verification.logging.LoggingFilter</filter-class>
69
</filter>
70
71
<filter-mapping>
72
<filter-name>LoggingFilter</filter-name>
73
<url-pattern>/*</url-pattern>
74
</filter-mapping>
75
</web-app>
76

Let's get started!


If you have already read through the 2FA tutorial, this User Model probably looks very similar. We need to make sure that our User model contains a phone number, country code so that the user can be verified with Authy.

User model definition and JPA mappings

user-model-definition-and-jpa-mappings page anchor
1
package com.twilio.verification.model;
2
3
import javax.persistence.*;
4
import java.util.Date;
5
6
@SuppressWarnings("unused")
7
@Entity
8
@Table(name = "users")
9
public class User {
10
@Id
11
@GeneratedValue(strategy = GenerationType.IDENTITY)
12
@Column(name = "id")
13
private int id;
14
15
@Column(name = "name")
16
private String name;
17
18
@Column(name = "email")
19
private String email;
20
21
@Column(name = "password")
22
private String password;
23
24
@Column(name = "country_code")
25
private String countryCode;
26
27
@Column(name = "phone_number")
28
private String phoneNumber;
29
30
@Column(name = "authy_id")
31
private int authyId;
32
33
@Column(name = "verified")
34
private boolean verified;
35
36
@Column(name = "date")
37
private Date date;
38
39
public User() {
40
}
41
42
public User(String name, String email, String password, String countryCode, String phoneNumber, int authyId) {
43
this.name = name;
44
this.email = email;
45
this.password = password;
46
this.countryCode = countryCode;
47
this.phoneNumber = phoneNumber;
48
this.authyId = authyId;
49
this.verified = false;
50
this.date = new Date();
51
}
52
53
public int getId() {
54
return id;
55
}
56
57
public void setId(int id) {
58
this.id = id;
59
}
60
61
public String getName() {
62
return name;
63
}
64
65
public void setName(String name) {
66
this.name = name;
67
}
68
69
public String getEmail() {
70
return email;
71
}
72
73
public void setEmail(String email) {
74
this.email = email;
75
}
76
77
public String getPassword() {
78
return password;
79
}
80
81
public void setPassword(String password) {
82
this.password = password;
83
}
84
85
public String getCountryCode() {
86
return countryCode;
87
}
88
89
public void setCountryCode(String countryCode) {
90
this.countryCode = countryCode;
91
}
92
93
public String getPhoneNumber() {
94
return phoneNumber;
95
}
96
97
public void setPhoneNumber(String phoneNumber) {
98
this.phoneNumber = phoneNumber;
99
}
100
101
public String getFullPhoneNumber() {
102
return countryCode + phoneNumber;
103
}
104
105
public int getAuthyId() {
106
return authyId;
107
}
108
109
public void setAuthyId(int authyId) {
110
this.authyId = authyId;
111
}
112
113
public boolean isVerified() {
114
return verified;
115
}
116
117
public void setVerified(boolean verified) {
118
this.verified = verified;
119
}
120
121
public Date getDate() {
122
return date;
123
}
124
125
public void setDate(Date date) {
126
this.date = date;
127
}
128
}
129

Next we will see how to handle the new user form.


When we create a new user, we ask for a name, email address, and a password. In order to validate a new account we also ask the user for a mobile number with a country code. We will use Authy to send a one-time password via SMS to this phone number.

It is now the servlet's responsibility to verify that the user provides the necessary information to create a new user. If the user is created successfully, they will be logged into the system automatically.

Handle registration of new accounts

handle-registration-of-new-accounts page anchor
1
package com.twilio.verification.servlet;
2
3
import com.authy.AuthyApiClient;
4
import com.twilio.verification.lib.RequestParametersValidator;
5
import com.twilio.verification.lib.SessionManager;
6
import com.twilio.verification.model.User;
7
import com.twilio.verification.repository.UsersRepository;
8
9
import javax.servlet.ServletException;
10
import javax.servlet.http.HttpServlet;
11
import javax.servlet.http.HttpServletRequest;
12
import javax.servlet.http.HttpServletResponse;
13
import java.io.IOException;
14
15
public class RegistrationServlet extends HttpServlet {
16
17
private final UsersRepository usersRepository;
18
private final SessionManager sessionManager;
19
private final AuthyApiClient authyClient;
20
21
@SuppressWarnings("unused")
22
public RegistrationServlet() {
23
this(
24
new UsersRepository(),
25
new SessionManager(),
26
new AuthyApiClient(System.getenv("AUTHY_API_KEY"))
27
);
28
}
29
30
public RegistrationServlet(UsersRepository usersRepository, SessionManager sessionManager, AuthyApiClient authyClient) {
31
this.usersRepository = usersRepository;
32
this.sessionManager = sessionManager;
33
this.authyClient = authyClient;
34
}
35
36
protected void doPost(HttpServletRequest request, HttpServletResponse response)
37
throws ServletException, IOException {
38
39
String name = request.getParameter("name");
40
String email = request.getParameter("email");
41
String password = request.getParameter("password");
42
String countryCode = request.getParameter("countryCode");
43
String phoneNumber = request.getParameter("phoneNumber");
44
45
if (validateRequest(request)) {
46
47
com.authy.api.User authyUser = authyClient.getUsers().createUser(email, phoneNumber, countryCode);
48
49
// Create user remotely
50
if (authyUser.isOk()) {
51
int authyUserId = authyUser.getId();
52
// Create user locally
53
User user = usersRepository.create(new User(name, email, password, countryCode, phoneNumber, authyUserId));
54
55
// Request SMS authentication
56
authyClient.getUsers().requestSms(authyUserId);
57
58
sessionManager.partialLogIn(request, user.getId());
59
response.sendRedirect("/verify-code");
60
}
61
} else {
62
preserveStatusRequest(request, name, email, countryCode, phoneNumber);
63
request.getRequestDispatcher("/registration.jsp").forward(request, response);
64
}
65
}
66
67
private boolean validateRequest(HttpServletRequest request) {
68
RequestParametersValidator validator = new RequestParametersValidator(request);
69
70
return validator.validatePresence("name", "email", "password", "countryCode", "phoneNumber")
71
&& validator.validateEmail("email");
72
}
73
74
private void preserveStatusRequest(
75
HttpServletRequest request,
76
String name,
77
String email,
78
String countryCode,
79
String phoneNumber) {
80
request.setAttribute("name", name);
81
request.setAttribute("email", email);
82
request.setAttribute("countryCode", countryCode);
83
request.setAttribute("phoneNumber", phoneNumber);
84
}
85
}
86
87

Now the user is logged in but not verified. In the next steps we'll learn how to verify the user using Authy.


In .environment we list configuration parameters for the application. These are pulled from system environment variables, which is a helpful way to access sensitive values (like API keys). This prevents us from accidentally checking them into source control. We use the System.getenv method to load the key and inject the AuthyApiClient into the RegistrationServlet class.

Now we need our Authy production key (sign up for Authy here(link takes you to an external page)). When you create an Authy application the production key is found on the dashboard.

Authy dashboard.

Register your AuthyAPIClient with your Authy API key

register-your-authyapiclient-with-your-authy-api-key page anchor
1
package com.twilio.verification.servlet;
2
3
import com.authy.AuthyApiClient;
4
import com.twilio.verification.lib.RequestParametersValidator;
5
import com.twilio.verification.lib.SessionManager;
6
import com.twilio.verification.model.User;
7
import com.twilio.verification.repository.UsersRepository;
8
9
import javax.servlet.ServletException;
10
import javax.servlet.http.HttpServlet;
11
import javax.servlet.http.HttpServletRequest;
12
import javax.servlet.http.HttpServletResponse;
13
import java.io.IOException;
14
15
public class RegistrationServlet extends HttpServlet {
16
17
private final UsersRepository usersRepository;
18
private final SessionManager sessionManager;
19
private final AuthyApiClient authyClient;
20
21
@SuppressWarnings("unused")
22
public RegistrationServlet() {
23
this(
24
new UsersRepository(),
25
new SessionManager(),
26
new AuthyApiClient(System.getenv("AUTHY_API_KEY"))
27
);
28
}
29
30
public RegistrationServlet(UsersRepository usersRepository, SessionManager sessionManager, AuthyApiClient authyClient) {
31
this.usersRepository = usersRepository;
32
this.sessionManager = sessionManager;
33
this.authyClient = authyClient;
34
}
35
36
protected void doPost(HttpServletRequest request, HttpServletResponse response)
37
throws ServletException, IOException {
38
39
String name = request.getParameter("name");
40
String email = request.getParameter("email");
41
String password = request.getParameter("password");
42
String countryCode = request.getParameter("countryCode");
43
String phoneNumber = request.getParameter("phoneNumber");
44
45
if (validateRequest(request)) {
46
47
com.authy.api.User authyUser = authyClient.getUsers().createUser(email, phoneNumber, countryCode);
48
49
// Create user remotely
50
if (authyUser.isOk()) {
51
int authyUserId = authyUser.getId();
52
// Create user locally
53
User user = usersRepository.create(new User(name, email, password, countryCode, phoneNumber, authyUserId));
54
55
// Request SMS authentication
56
authyClient.getUsers().requestSms(authyUserId);
57
58
sessionManager.partialLogIn(request, user.getId());
59
response.sendRedirect("/verify-code");
60
}
61
} else {
62
preserveStatusRequest(request, name, email, countryCode, phoneNumber);
63
request.getRequestDispatcher("/registration.jsp").forward(request, response);
64
}
65
}
66
67
private boolean validateRequest(HttpServletRequest request) {
68
RequestParametersValidator validator = new RequestParametersValidator(request);
69
70
return validator.validatePresence("name", "email", "password", "countryCode", "phoneNumber")
71
&& validator.validateEmail("email");
72
}
73
74
private void preserveStatusRequest(
75
HttpServletRequest request,
76
String name,
77
String email,
78
String countryCode,
79
String phoneNumber) {
80
request.setAttribute("name", name);
81
request.setAttribute("email", email);
82
request.setAttribute("countryCode", countryCode);
83
request.setAttribute("phoneNumber", phoneNumber);
84
}
85
}
86
87

Now let's check out the Servlet handling a new user registration and see how it sends a token upon account creation.


Sending a Token on Account Creation

sending-a-token-on-account-creation page anchor

Once the user has an authyId we can actually send a verification code to that user's mobile phone using the Java Client for Authy(link takes you to an external page).

When our user is created successfully via the form we implemented, we send a token to the user's mobile phone to verify their account in our servlet.

Handle registration of new accounts

handle-registration-of-new-accounts-1 page anchor
1
package com.twilio.verification.servlet;
2
3
import com.authy.AuthyApiClient;
4
import com.twilio.verification.lib.RequestParametersValidator;
5
import com.twilio.verification.lib.SessionManager;
6
import com.twilio.verification.model.User;
7
import com.twilio.verification.repository.UsersRepository;
8
9
import javax.servlet.ServletException;
10
import javax.servlet.http.HttpServlet;
11
import javax.servlet.http.HttpServletRequest;
12
import javax.servlet.http.HttpServletResponse;
13
import java.io.IOException;
14
15
public class RegistrationServlet extends HttpServlet {
16
17
private final UsersRepository usersRepository;
18
private final SessionManager sessionManager;
19
private final AuthyApiClient authyClient;
20
21
@SuppressWarnings("unused")
22
public RegistrationServlet() {
23
this(
24
new UsersRepository(),
25
new SessionManager(),
26
new AuthyApiClient(System.getenv("AUTHY_API_KEY"))
27
);
28
}
29
30
public RegistrationServlet(UsersRepository usersRepository, SessionManager sessionManager, AuthyApiClient authyClient) {
31
this.usersRepository = usersRepository;
32
this.sessionManager = sessionManager;
33
this.authyClient = authyClient;
34
}
35
36
protected void doPost(HttpServletRequest request, HttpServletResponse response)
37
throws ServletException, IOException {
38
39
String name = request.getParameter("name");
40
String email = request.getParameter("email");
41
String password = request.getParameter("password");
42
String countryCode = request.getParameter("countryCode");
43
String phoneNumber = request.getParameter("phoneNumber");
44
45
if (validateRequest(request)) {
46
47
com.authy.api.User authyUser = authyClient.getUsers().createUser(email, phoneNumber, countryCode);
48
49
// Create user remotely
50
if (authyUser.isOk()) {
51
int authyUserId = authyUser.getId();
52
// Create user locally
53
User user = usersRepository.create(new User(name, email, password, countryCode, phoneNumber, authyUserId));
54
55
// Request SMS authentication
56
authyClient.getUsers().requestSms(authyUserId);
57
58
sessionManager.partialLogIn(request, user.getId());
59
response.sendRedirect("/verify-code");
60
}
61
} else {
62
preserveStatusRequest(request, name, email, countryCode, phoneNumber);
63
request.getRequestDispatcher("/registration.jsp").forward(request, response);
64
}
65
}
66
67
private boolean validateRequest(HttpServletRequest request) {
68
RequestParametersValidator validator = new RequestParametersValidator(request);
69
70
return validator.validatePresence("name", "email", "password", "countryCode", "phoneNumber")
71
&& validator.validateEmail("email");
72
}
73
74
private void preserveStatusRequest(
75
HttpServletRequest request,
76
String name,
77
String email,
78
String countryCode,
79
String phoneNumber) {
80
request.setAttribute("name", name);
81
request.setAttribute("email", email);
82
request.setAttribute("countryCode", countryCode);
83
request.setAttribute("phoneNumber", phoneNumber);
84
}
85
}
86
87

When the code is sent we redirect to another page where the user can enter the token they received, therefore completing the verification process.


This servlet method handles the submission form. It needs to:

  • Get the current user.
  • Verify the code that was entered by the user.
  • If the code entered was valid, flip a Boolean flag on the user model to indicate the account was verified.

Verify an Authy code

verify-an-authy-code page anchor

The Authy client(link takes you to an external page) provides us with a verify() method that allows us to pass a user id and a token. In this case we just need to check that the API request was successful and, if so, set the User's verified field to true.

1
package com.twilio.verification.servlet;
2
3
import com.authy.AuthyApiClient;
4
import com.authy.api.Token;
5
import com.twilio.verification.lib.RequestParametersValidator;
6
import com.twilio.verification.lib.Sender;
7
import com.twilio.verification.lib.SessionManager;
8
import com.twilio.verification.model.User;
9
import com.twilio.verification.repository.UsersRepository;
10
11
import javax.servlet.ServletException;
12
import javax.servlet.http.HttpServlet;
13
import javax.servlet.http.HttpServletRequest;
14
import javax.servlet.http.HttpServletResponse;
15
import java.io.IOException;
16
17
public class VerifyCodeServlet extends HttpServlet {
18
19
private final UsersRepository usersRepository;
20
private final SessionManager sessionManager;
21
private final AuthyApiClient authyClient;
22
private final Sender sender;
23
24
@SuppressWarnings("unused")
25
public VerifyCodeServlet() {
26
this(
27
new UsersRepository(),
28
new SessionManager(),
29
new AuthyApiClient(System.getenv("AUTHY_API_KEY")),
30
new Sender()
31
);
32
}
33
34
public VerifyCodeServlet(
35
UsersRepository usersRepository, SessionManager sessionManager, AuthyApiClient authyClient, Sender sender) {
36
this.usersRepository = usersRepository;
37
this.authyClient = authyClient;
38
this.sessionManager = sessionManager;
39
this.sender = sender;
40
}
41
42
protected void doGet(HttpServletRequest request, HttpServletResponse response)
43
throws ServletException, IOException {
44
45
request.getRequestDispatcher("/verifyCode.jsp").forward(request, response);
46
}
47
48
protected void doPost(HttpServletRequest request, HttpServletResponse response)
49
throws ServletException, IOException {
50
51
String code = request.getParameter("code");
52
53
if (validateRequest(request)) {
54
int userId = sessionManager.getLoggedUserId(request);
55
User user = usersRepository.find(userId);
56
57
Token token = authyClient.getTokens().verify(user.getAuthyId(), code);
58
if (token.isOk()) {
59
user.setVerified(true);
60
usersRepository.update(user);
61
// Send SMS confirmation
62
sender.send(user.getFullPhoneNumber(), "You did it! Sign up complete :3");
63
64
sessionManager.logIn(request, userId);
65
response.sendRedirect("/account");
66
} else {
67
request.setAttribute("codeError", "Incorrect code, please try again");
68
request.getRequestDispatcher("/verifyCode.jsp").forward(request, response);
69
}
70
} else {
71
request.getRequestDispatcher("/verifyCode.jsp").forward(request, response);
72
}
73
}
74
75
76
private boolean validateRequest(HttpServletRequest request) {
77
RequestParametersValidator validator = new RequestParametersValidator(request);
78
79
return validator.validatePresence("code");
80
}
81
}
82

That's all for token verification! However, our verification form wouldn't be very usable if there wasn't a way to resend a verification code if the message didn't arrive at the end user's handset.


Since the form for re-sending the code(link takes you to an external page) is very short, we're going to skip that for this tutorial. Let's just look at the servlet.

This method loads the user associated with the request and then uses the same Authy API method we used earlier to resend the code.

Re-send an Authy verification code

re-send-an-authy-verification-code page anchor
1
package com.twilio.verification.servlet;
2
3
import com.authy.AuthyApiClient;
4
import com.twilio.verification.lib.SessionManager;
5
import com.twilio.verification.model.User;
6
import com.twilio.verification.repository.UsersRepository;
7
8
import javax.servlet.ServletException;
9
import javax.servlet.http.HttpServlet;
10
import javax.servlet.http.HttpServletRequest;
11
import javax.servlet.http.HttpServletResponse;
12
import java.io.IOException;
13
14
public class ResendTokenServlet extends HttpServlet {
15
16
private final UsersRepository usersRepository;
17
private final SessionManager sessionManager;
18
private final AuthyApiClient authyClient;
19
20
@SuppressWarnings("unused")
21
public ResendTokenServlet() {
22
this(
23
new UsersRepository(),
24
new SessionManager(),
25
new AuthyApiClient(System.getenv("AUTHY_API_KEY"))
26
);
27
}
28
29
public ResendTokenServlet(
30
UsersRepository usersRepository, SessionManager sessionManager, AuthyApiClient authyClient) {
31
this.usersRepository = usersRepository;
32
this.sessionManager = sessionManager;
33
this.authyClient = authyClient;
34
}
35
36
protected void doPost(HttpServletRequest request, HttpServletResponse response)
37
throws ServletException, IOException {
38
39
int userId = sessionManager.getLoggedUserId(request);
40
User user = usersRepository.find(userId);
41
42
// Request SMS authentication
43
authyClient.getUsers().requestSms(user.getAuthyId());
44
45
response.sendRedirect("/verify-token");
46
}
47
}
48

To wrap things up, let's implement the last step where we confirm that the user's account has been verified with a text message.


Sending the Confirmation Message

sending-the-confirmation-message page anchor

In this example, we create a single instance of the Twilio REST API helper, called client.

Then we need to get the account, the messageFactory, and finally use its sendMessage method in order to send an SMS to the user's phone.

Send a confirmation with a TwilioRestClient wrapper

send-a-confirmation-with-a-twiliorestclient-wrapper page anchor
1
package com.twilio.verification.lib;
2
3
import com.twilio.http.TwilioRestClient;
4
import com.twilio.rest.api.v2010.account.MessageCreator;
5
import com.twilio.type.PhoneNumber;
6
import com.twilio.verification.lib.Twilio.Config;
7
8
public class Sender {
9
10
private final TwilioRestClient client;
11
12
public Sender() {
13
client = new TwilioRestClient.Builder(Config.getAccountSid(), Config.getAuthToken()).build();
14
}
15
16
public Sender(TwilioRestClient client) {
17
this.client = client;
18
}
19
20
public void send(String to, String message) {
21
new MessageCreator(
22
new PhoneNumber(to),
23
new PhoneNumber(Config.getPhoneNumber()),
24
message
25
).create(client);
26
}
27
28
}
29

Congratulations! You've successfully verified new user accounts with Authy. Where can we take it from here?


If you're a Java developer working with Twilio, you might want to check out these other tutorials:

Click-To-Call

Put a button on your web page that connects visitors to live support or salespeople via telephone.

Automated Survey

Instantly collect structured data from your users with a survey conducted over a voice call or SMS text messages.

Need some help?

Terms of service

Copyright © 2024 Twilio Inc.