This article shows how to implement two factor authentication using Twilio and IdentityServer4 using Identity. On the Microsoft’s Two-factor authentication with SMS documentation, Twilio and ASPSMS are promoted, but any SMS provider can be used.
Code: https://github.com/damienbod/AspNetCoreID4External
2017-09-23 Updated to ASP.NET Core 2.0
Setting up Twilio
Create an account and login to https://www.twilio.com/
Now create a new phone number and use the Twilio documentation to set up your account to send SMS messages. You need the Account SID, Auth Token and the Phone number which are required in the application.
The phone number can be configured here:
https://www.twilio.com/console/phone-numbers/incoming
Adding the SMS support to IdentityServer4
Add the Twilio Nuget package to the IdentityServer4 project.
<PackageReference Include="Twilio" Version="5.6.5" />
The Twilio settings should be a secret, so these configuration properties are added to the app.settings.json file with dummy values. These can then be used for the deployments.
"TwilioSettings": { "Sid": "dummy", "Token": "dummy", "From": "dummy" }
A configuration class is then created so that the settings can be added to the DI.
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace IdentityServerWithAspNetIdentity.Services { public class TwilioSettings { public string Sid { get; set; } public string Token { get; set; } public string From { get; set; } } }
Now the user secrets configuration needs to be setup on your dev PC. Right click the IdentityServer4 project and add the user secrets with the proper values which you can get from your Twilio account.
{ "MicrosoftClientId": "your_secret..", "MircosoftClientSecret": "your_secret..", "TwilioSettings": { "Sid": "your_secret..", "Token": "your_secret..", "From": "your_secret..", } }
The configuration class is then added to the DI in the Startup class ConfigureServices method.
var twilioSettings = Configuration.GetSection("TwilioSettings"); services.Configure<TwilioSettings>(twilioSettings);
Now the TwilioSettings can be added to the AuthMessageSender class which is defined in the MessageServices file, if using the IdentityServer4 samples.
private readonly TwilioSettings _twilioSettings; public AuthMessageSender(ILogger<AuthMessageSender> logger, IOptions<TwilioSettings> twilioSettings) { _logger = logger; _twilioSettings = twilioSettings.Value; }
This class is also added to the DI in the startup class.
services.AddTransient<ISmsSender, AuthMessageSender>();
Now the TwilioClient can be setup to send the SMS in the SendSmsAsync method.
public Task SendSmsAsync(string number, string message) { // Plug in your SMS service here to send a text message. _logger.LogInformation("SMS: {number}, Message: {message}", number, message); var sid = _twilioSettings.Sid; var token = _twilioSettings.Token; var from = _twilioSettings.From; TwilioClient.Init(sid, token); MessageResource.CreateAsync(new PhoneNumber(number), from: new PhoneNumber(from), body: message); return Task.FromResult(0); }
The SendCode.cshtml view can now be changed to send the SMS with the style, layout you prefer.
<form asp-controller="Account" asp-action="SendCode" asp-route-returnurl="@Model.ReturnUrl" method="post" class="form-horizontal"> <input asp-for="RememberMe" type="hidden" /> <input asp-for="SelectedProvider" type="hidden" value="Phone" /> <input asp-for="ReturnUrl" type="hidden" value="@Model.ReturnUrl" /> <div class="row"> <div class="col-md-8"> <button type="submit" class="btn btn-default">Send a verification code using SMS</button> </div> </div> </form>
In the VerifyCode.cshtml, the ReturnUrl from the model property must be added to the form as a hidden item, otherwise your client will not be redirected back to the calling app.
<form asp-controller="Account" asp-action="VerifyCode" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal"> <div asp-validation-summary="All" class="text-danger"></div> <input asp-for="Provider" type="hidden" /> <input asp-for="RememberMe" type="hidden" /> <input asp-for="ReturnUrl" type="hidden" value="@Model.ReturnUrl" /> <h4>@ViewData["Status"]</h4> <hr /> <div class="form-group"> <label asp-for="Code" class="col-md-2 control-label"></label> <div class="col-md-10"> <input asp-for="Code" class="form-control" /> <span asp-validation-for="Code" class="text-danger"></span> </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <div class="checkbox"> <input asp-for="RememberBrowser" /> <label asp-for="RememberBrowser"></label> </div> </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <button type="submit" class="btn btn-default">Submit</button> </div> </div> </form>
Testing the application
If using an existing client, you need to update the Identity in the database. Each user requires that the TwoFactoredEnabled field is set to true and a mobile phone needs to be set in the phone number field, (Or any phone which can accept SMS)
Now login with this user:
The user is redirected to the send SMS page. Click the send SMS button. This sends a SMS to the phone number defined in the Identity for the user trying to authenticate.
You should recieve an SMS. Enter the code in the verify view. If no SMS was sent, check your Twilio account logs.
After a successful code validation, the user is redirected back to the consent page for the client application. If not redirected, the return url was not set in the model.
Links:
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/2fa
[…] Implementing Two-factor authentication with IdentityServer4 and Twilio (Damien Bowden) […]
[…] Implementing Two-factor authentication with IdentityServer4 and Twilio (Damien Bowden) […]
Great tutorial! Really shows how accessible Identity Server is. I still feel a lot of teams don’t really know about Identity Server, nor of service based alternative like B2C. Still see a lot of JavaScript apps that rely on a local based cookie solution because its whats always worked in the past then the team uses some kind of custom solution to communicate with other applications in their infrastructure, which in the end makes things 10x more complicated yet less secure than using an Oauth /OpenId based approach.
Hi Andrew thanks, javascript and cookies are scary. Greetings Damien
[…] on July 19, 2017 submitted by /u/justintimecoder [link] [comments] Leave a […]
Hi Damien,
Thanks for your continuous effort to provide first class material regarding .net core and IdentityServer.
I have a question and I’m sure you know the answer 🙂
What do you do in your angular SPA (using IdentityServer and asp.net identity) for coping with the different account management tasks like change password, add 2FA, add mobile phone, verify number, etc; … Sometimes there is a need that there tasks are accessible directly from the SPA.
Do you just call the MVC views directly from the angular app (e.g. via window.location.href or via a popup) or do you use another approach for this?
Thanks a lot for shedding a light on this.
Warm regards
paul.
Hi Paul, I create an API for this. Then you can protect it with the proper scheme, eg a token and not a cookie
Here’s a basic example:
https://github.com/damienbod/AspNet5IdentityServerAngularImplicitFlow/blob/master/src/ResourceWithIdentityServerWithClient/angularApp/app/user-management/UserManagementService.ts
missing the scheme check on the server though.
HI Damien,
Thanks a lot for the prompt reply.
Your scenario is about admin screens (admin on other regular users) in angular which are served by one broad web api controller (the userManagement controller).
My scenario is not directly about admin on other users, but for regular users who want to update there password, activate 2FA, add a mobile phone, the forgot password scenario…
Now, anywayn when the user logs in, the asp.net Account/login view is used for this, so the user is anyway redirected away from the SPA.(potentially via a SPA managed popup)
So, if i understand you correctly you would suggest to make for the above mentioned use cases corresponding asp.net web api controllers in such a way the scenarios can be managed directly from SPA screens rather than the asp.net mvc screens.
I’m wondering if the same approach as for the regular login screen can not be maintained? But obviously a mechanism need to be used in such a way the UX stays ok ?
Any ideas on that?
[…] Implementing Two-factor authentication with IdentityServer4 and Twilio […]
Hello Damien, thanks for the wonderful blog posts you share with us. How is it possible to use Google Authenticator for instance to generate a OT pass code? Thanks
hi! Why this is no longer recommended ?
Why this is no longer recommended ??
SMS can be comprised, an authenticator app or Fido2 is now recommended as a better or more secure solution. But to be clear, it is still better as no 2FA
Greetings Damien
Hi, We are developing MVC application with SSO using IdentityServer3. I need to implement Two factor authentication using Twilio. Can you please provide the sample for IdentityServer3 (.Net Framework)?
Thanks in advance.