Extend identity for SMS OTP based login - authentication

I have trying to implment one time registration verification & daily login using SMS OTP for my app using asp.net core identity implementation.
It is one time token, which should expire in 15 minutes if not used
User should request it again in case its expired or lost
Searching around for it, all the implementation provide details about MFA or Google Authenticator based verification, where this scenario is slightly different.
The Token will not be generated by the Server, and not the Authenticator app.
I need to store token along with its genrated at time.
The token will be 6 digit SMS.
The scenario is more similar to password less auth mentioned here, but then the token in that case is not stored, I need to store it with Validity, not sure how to extend .net core identity to match above requirement.
This is fairly standard way of phone number authentication
I know this is not a standard SO format, but I am at loss from where to start

I know this is an old question, but I found myself here with the same problem, and information about this is surprisingly thin on the ground. Likely as Microsoft recommend using (2FA) authenticator apps, using a Time-based One-time Password Algorithm (TOTP) rather than an OTP with SMS/Email.
Not the intended purpose, but nevertheless the following will allow you to generate and save a time limited (3 minutes) 6 digit OTP, associate it with a user and then use it to verify them using ASP.NET Core Identity.
GenerateChangePhoneNumberTokenAsync
var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, model.PhoneNumber);
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.usermanager-1.generatechangephonenumbertokenasync
and
VerifyChangePhoneNumberTokenAsync
bool valid = await _userManager.VerifyChangePhoneNumberTokenAsync(user, code, model.PhoneNumber);
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.usermanager-1.verifychangephonenumbertokenasync
This can be seen being implemented in the documentation posted by Erik & paulsm4
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/2fa?view=aspnetcore-1.1&viewFallbackFrom=aspnetcore-3.1
A link to the code
https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/security/authentication/2fa/sample/Web2FA
A link to the controller where this is implemented
https://github.com/dotnet/AspNetCore.Docs/blob/master/aspnetcore/security/authentication/2fa/sample/Web2FA/Controllers/ManageController.cs

Related

Is it acceptable to use GenerateChangePhoneNumberTokenAsync() to confirm an email instead of phone number?

I'm building an API and a Mobile APP in Xamarin. I don't want to confirm the phone number as I'd have to use Twilio or other SMS providers, instead, I want to confirm an email. At the same time, I don't want to create an email token to be sent to the user with a link to click, as API is not MVC and won't have any views.
Instead, I want a 6 digit code to be emailed to the user and then I will create an endpoint in the API where the user will submit that code via the mobile APP, to confirm the email. For example:
var code = await _userManager.GenerateChangePhoneNumberTokenAsync(newUser, newUser.Email);
This creates the code, notice I am passing users email rather than the phone number. This code is now emailed to the user, and the user enters this in the mobile APP. Then:
var confirmed = await _userManager.VerifyChangePhoneNumberTokenAsync(newUser, code, newUser.Email);
This confirms that the code is correct. The boolean resulting from this I will then use to manually set EmailConfirmed in the DB to true
It works. Is it acceptable though? Is there any reason why I shouldn't be doing this?
One reason that pops up is that even though it's just a validation code, semantically the function is for phone codes, so it could have some "gotchas" introduced in the future if you use it for e-mails.
By reading the source you can see that the implementation is currently based upon RFC 6238: Time-Based One-Time Password Algorithm, which is generic enough for the e-mail usage as well.
Thus, you know that by using the same method, it's as secure as the RFC 6238 specification as implemented in ASP.NET Identity Core.
You can't just use the class because the access modifier is internal, but following the same idea, there are OTP Libraries for .NET based on the same principle.
Using one of them would ensure that the implementation is as clean and generic as possible in my opinion, but for the quick and dirty solution with the current version of ASP.NET Identity Core, I'd see no issues with the approach.

Understanding Sign in with Apple using Django Rest Framework (DRF)

I am trying to implement Sign in with Apple in my iOS app and Django Rest Framework (DRF) application. I want to know if I understand the workflow correctly.
Currently, I am using the libraries python-social-auth and rest_social_auth, and rest_framework_simplejwt.authentication.JWTAuthentication for authentication. The problem is that I set the refresh tokens to expire in one week (this should really be one day). At that point, I need to use the refresh token that Apple originally returned in their first authentication request, but python-social-auth does not persist those.
Specifically, I am wondering how I can get access to those original refresh tokens. More generally, I am wondering if this functionally has already been written in python-social-auth.
After a year and a half, "I" finally figured this out.
I was conflating the device Sign in with Apple with the Sign in with Apple Rest API. If you are developing in iOS/React Native, you do not need to make any calls to the Sign in with Apple Rest API.
You do need to make a call to an Apple auth server, but not a Sign in with Apple Rest API server. The Apple auth server will return a public key that you use to then confirm the authenticity of the identity token that Apple send to you on the device.
I borrowed heavily from this Gist, but I believe it is outdated because Apple is now cycling through (at least at the time of this post) 3 different keys. I also used Chris Herbert's post as a resource.
def _fetch_apple_public_key(kid):
global APPLE_LAST_KEY_FETCH
global APPLE_PUBLIC_KEYS
apple_public_key = APPLE_PUBLIC_KEYS.get(kid)
if (APPLE_LAST_KEY_FETCH + APPLE_KEY_CACHE_EXP) < int(time()) or apple_public_key is None:
keys_payload = requests.get(APPLE_PUBLIC_KEY_URL).json()
for key_payload in keys_payload["keys"]:
if key_payload.get('kid') == kid:
APPLE_PUBLIC_KEYS[kid] = RSAAlgorithm.from_jwk(json.dumps(key_payload))
APPLE_LAST_KEY_FETCH = int(time())
return APPLE_PUBLIC_KEYS[kid]
You can get the kid from the header of the identity token:
headers = jwt.get_unverified_header(user_token)
kid = headers.get('kid')

How to Implement Two Factor Authentication Via Email in ASP.Net Core 2?

I am using ASP.NET Core 2.2 for a web server, In each time a user login to the website, after entering a correct email & password, I need to send a message containing a 4-digits PIN Code to user email, to use it as Email Two Factor Authentication, and this PIN Code, should expire after 10 minutes after sending it.
I can do this manually (generating random PIN Codes, saving them in Database, verifying them using if statements, etc...), this would work, but I created this question to ask how to do this using ASP.NET Core 2 available features (which can spare the database table for me).
I tried UserManager.GenerateTwoFactorTokenAsync(TUser, String) Method, to generate a token and send it to email:
var token = await _userManager.GenerateTwoFactorTokenAsync(user, "Default");
SendLoginTokenToUserEmail(user, token);
and used UserManager.VerifyTwoFactorTokenAsync(TUser, String, String) to verify it:
var verified = await _userManager.VerifyTwoFactorTokenAsync(user, "Default", token);
This worked perfectly, but my problem was that the generated token wasn't a 4-Digit PIN Code, and its expiration time wasn't 10 minutes (I think the default is 1 day).
So, my Question is: How to Customize the generated token by UserManager for Two Factor Authentication in ASP.NET Core 2.2?
Can this done by creating a custom token provider? (I am using Default Token Provider here) if so, what is the steps to do so? I spent hours surfing Docs and ASP.NET Core 2 Articles, but did't find what I need.
PS: If there is any other way other than UserManager, I am all ears, but I thought this might be the best way, especially UserManager is used everywhere in our system (for login, password-reset, etc...).

Architecture Design - REST API to support Facebook Login done by Mobile app

I am trying to design REST APIs to support various mobile clients (iOS and Android apps). These apps will let user login using facebook login along with our own email authentication. You can refer to the diagram below to understand my design
There are two levels of authorization take place:
First one is "Client (or App) Authorization" that uses OAuth2. So when user install our app on mobile device, and starts app, then very first thing, app makes "Client (App) Authorization" as shown in above diagram (1st image). And server sends back an long-lived access_token to client to use for all subsequent calls. Here my question are:
Q1) You can see client is sending client_key and client_secret and I am storing them in client_info table. Should this secret be in plain text or it should be in decryt-able format? If I encrypt it, I still need to keep encryption key somewhere in my system. So how it will make it secure? Also in every call, decryption will be an overhead.
Q2) Is it ok to cache access_token for the client in plain text format in redis and use that cache first?
Q3) In order to be extra safe, I am asking clients to send appsecret_proof to make sure the access_token, they are sending belongs to this client only. It uses the same concept as Facebook https://developers.facebook.com/docs/graph-api/securing-requests#appsecret_proof. And it is hash_hmac('sha256', access_token, client_secret)
Q4) We will only have our own 2 mobile app (each for iOS and Android) and not providing third party to use our API to develop other apps. That means, our client_info table will only have two rows one for each type of apps. So is it okay, that in app code, we keep client_key and client_secret hardcoded? If yes, then in future when we have to invalidate and use new secret then how will we achieve replacing those info?
Q5) Since it is our own apps for couple of years, so there would be multiple access_token will get created against same client_key and client_secret. In order to save all of them, is it a good idea to store client_key as key and an array of all access_tokens as value in redis. In future, when we will open our API to third party, then this redis storage design can still scale?
=================
Later on, user decides to perform some actions on my app, for that we need user to login to his account. For that user click on "facebook login". My app gets facebook access_token and fb user's id from facebook and pass those info to API server (as shown in 2nd diagram). API server takes that token and call facebook API to validate its access_token. Once token is validated, server uses some metadata related to that user along with FB access token to generate our own user_access_token, lets say utoken. And pass that utoken back to client to pass back in every subsequent user specific API calls. Here my questions are:
Q1) Is it ok to save that utoken in database, user_token table. Should this utoken be in plain text or it should be in decryt-able format? If I encrypt it, I still need to keep encryption key somewhere in my system. So how it will make it secure? Also in every call, decryption will be an overhead.
Q2) In every user specific API calls, should I call facebook every time to check facebook access_token is still valid? I believe I should not, as that is not going to get anything to me. Please note, Facebook is ONLY used for "facebook login".
Q3) What are the information I should encrypt to generate utoken? I am thinking to have a hash or associative array of user's email, user id, role and facebook token and then serialize that data structure and finally encrypt it. Do you think that would be good enough. I understand its per my requirement, but as a standard or common app, are they good enough? Or is there any best practice?
Q4) Should client store utoken in its cookie/cache? Isn't that scary?
Q5) Please note user may have multiple devices, logged in with same user credential. That means, in user_token table, we would have to store multiple utokens for those logged-in session, while all of them will belong to the same user. Does that sound right?
A design proposal somewhat smiliar to mine REST API for website which uses Facebook for authentication
Q1.1: No!. Client credentials is not intended to be used that way. If your client is a Single Page App or a Mobile App, you will be forced to store your client credentials in an insecure environment, the user's machine. You should be using OAuth's Implicit flow
Q1.2: Assuming the token is short lived, no problem caching it. The key of OAuth, apart from ensuring that you can rely on other application to authenticate your users, is that you effectively substitute user or application credentials, which are long lived, with a short lived token. So if someone gains access to the token,at least, their access to the system will be limited in time.
Q1.3: Check out that facebook documentation:
Graph API calls can be made from clients or from your server on behalf of clients. Calls from a server can be better secured by adding a parameter called appsecret_proof.
It states that appsecret_proof is to be used for calls from the server on behalf of the user. The point here has to do with Q1.1. If you were storing your client_secret in your user's device, they could generate the appsecret_proof.
Q1.4: Again, No! You should have a good read of OAuth Specification and understand the different flow types and when to use each. Also bear in mind, that if you provide an API for your App the API is public for any one to abuse. The only difference is that it is not documented. The same will happen with a Web App. Once it is in the internet, I could write a scraper and abuse the Web App. This is perfectly normal, just bear in mind that anything on the internet is not private, it is just undocumented.
Q1.5: Again, tokens should be short lived. If their lifespan is the same of the credentials, which live until the user change them, then tokens lose their purpose.
Q2.1: You should save that token A ReST architecture uses a client cache constraint.
Q2.2: I don't think so. Facebook is just telling you that the user that obtained that token has some identity (an email, for example) that you can associate to a user in your system. Once you know that association you should't care much about the Facebook token but to make calls to Facebook API. But as you say, you are using it just for login.
Q2.3: Seems not bad but check again the Oauth Specification as you seem to be building an Implicit flow and using JWT tokens. As per what you want to store in your token, seems fine.
Q2.4: JWT tokens must be cached by the client. Nothing scary, because they are opaque to the client as they are encrypted. The client sends the JWT token with each request and the API server decrypts the token with a private key (that has never been exposed outside the server) and can check the identity of the user.
Q2.5: Remember short lived tokens. Tokens must expire!.

ASP .NET WebAPI default OWIN authentication - help clear things up

I have some general/how-does-it-work-inside questions about WebAPI and OWIN (specifically, the default configuration which is set up when you create new WebAPI project in VS2013 and select Individual user account authentication). I did that, then I registered (using jQuery post) and even logged in (received token which I included in Authorization header, receiving access to protected resource. I just have some more questions about it:
Are my data stored inside authentication token? I know my password isn't, but is token containing encrypted data, or is just a random string? These are the only 2 options that I can think of: either token contains encrypted data (userId, expiration date, etc.) and server app deciphers it and grants me access to resources, or token is a random string and all user data are stored on server (token is used as a key to obtain correct user data entry). If the second theory is right, the token <-> userData lookup must be stored somewhere - is it session, cache or database maybe?
If i wanted to make a RESTful API, what about Roles, etc. (in general - data beyond simple who-are-you identification that I need for every request)? Again: first thing that comes to mind is to store them inside token. But if the data grows large isn't that too much overhead to send with each request (plus headers themselves probably are limited in size)? Second thing is using external OAuth service (like Facebook or Twitter) - if the user authenticates using external token, I can't control what information does it contain. Alternative is to get the data I need from the database each time, but isn't it bad practice? Every single request would need an extra database call to collect user's role and check if he even has access to this particular part of application. I could store it in session, but RESTful API is supposed to be stateless.
Thanks for any help as I'm just starting to dig into OAuth and WebAPI authentication. I know that I can customize everything to work as I want (so use session to store user data, etc.), but I wanted to know what the good practices are and which of them are provided out of the box with default WebAPI project in VS2013 and which need to be implemented manually.
(1) the latter is correct. The server verify token by machine key and can decipher and validate its contents.
(2) You got that correct. Its best to keep the token size min. tbh I am looking to see what others are doing about this. (+1 for the question.)