Redirect user to another step of the SignUp - rest

I have an sign up form that have to save information one by one.
Example:
Client inputs email
Client sends request to validate if email already exists
If email doenst exists, save it in database and redirect user to the next step of the registration
Next step is saving user fullname
Client calls redirected endpoint to save user fullname and saves full name and gets another redirect URL
Calls the redirect endpoints received in the previous step (and goes on until it has the password, image... etc)
I was wondering about two possible solutions:
Use one of the 3xx http redirect status codes to redirect to each one of the steps endpoints, until the registration is completed.
Using a Patch endpoint that receives each one of the registration parameter one by request.
Anyone has an idea about which one is a good/bac practice, or if theres another solutions to this

Related

IdentityServer4 - redirect after registration

I have a simple setup with IdentityServer4 (custom user store) and Mvc client app. Some pages in the client app are protected. So for example when a user hits /pageX he gets redirected to IdentityServer for authentication. This works fine when the user exists, he just logs in and gets redirected.
If he is not registered, he is asked to register and he gets an activation code via email.
Then he goes to inbox, clicks activation link and is invited to login again.
Now, after activation and login, I would like to redirect him to the /pageX he originally asked.
My problem is - at this point I no longer have a valid returnUrl which contains /pageX encoded somehow. I tried using the returnUrl which works in simple login flow:
returnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DmyClientIdt%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A5501%252Fsignin-oidc%26response_type%3Did_token%26scope%3Dopenid%2520profile%26response_mode%3Dform_post%26nonce%3D636469643044666440.MmZlNzFlMWYtZThhMS00ZjFlLTgyYjYtMDU5NjRmODBhZmNkMzk1MzJiZWItODY2Yy00NzYwLWE4YjQtOGU5YWU5Y2IxMDJk%26state%3DCfDJ8IK-YquShZdNsC5l0tQGkLIvU-_O1FbdO5RV9KrOZ9hCTixBZc-YeVLkKB2mvHkV9U42U83N7RfFCHywKjdbGRGnpfqwgG08_ip1Pt2sAqfa_sPlwYOO7fSiKUbnk2IpA1BMWvfeXNwIeFB7AMv0q0Y2z7vjCTNWawwNS6m5EM3h9V0uCpHE-1H19VPhE0OQcXmmcaNViWbdmWE14VNTH8MYQaPfE90smHtRwYtbYaYhfj-g4ziXbhN6m_R6PYni1ApazIDUBOowEq6yV9ynF91SM82gohud4Ek3juozL-A4W_dTIBZnj1C5PMmUISWl9yw_UPOvTwsCskVH2OmavgI%26x-client-SKU%3DID_NET%26x-client-ver%3D2.1.4.0)
But if I use this return url after registration, I get a correlation error message.
Any idea how can I return the user back to his original requested /pageX?
The returnUrl (as sampled in the question) is a result of redirection from Authorize Endpoint to Login/Register Page. You need to use IdentityServer Interaction Service to retrieve the actual returnUrl.
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
context.RedirectUri will hold the actual url (/PageX), where user needs to be redirected after activation.
You can pass context.RedirectUri as a query parameter to the activation link and retrieve it on the activation page. When activation is complete you can redirect the user to the returnUrl.
string activationLink = "<your activation url>?return=" + returnUrl;
Check this docs
Basically this situation can be avoided by not providing a link to click in the confirmation email which will land the user in a different browser tab.
Instead of a link provide an n-digit code in the email and let the user enter the code in the already open browser tab where you still have access to the returnUrl

how to implement passwordless authentication in identityserver3

I'm looking for the correct way to customize or extend identityserver3 to implement passwordless authentication.
the user scenario is
user uses browser to go to website
website detects non-authenticated
user and redirects to idsrv3 instance
idsrv3 asks for email address (or uses a cookie stored one) and if email address matches a known user, sends an email with a link (e.g. like the registration or password reset link)
user clicks on link
idsrv3 instance checks if token in link matches a known user and is not expired
idsrv3 issues token
idsrv3 redirects to original url
after some reading, I think the correct way to customize idsrv3 would be to
create a custom viewservice
checks the emailaddress
generates and stores a token in the user account record
sends an email with a link consisting of a custom grant, the token and a returnurl
create a custom grant and corresponding validator
checks the incoming token and if valid returns a positive validation result linked to a user account
the normal idsrv3 token issuing flow takes over to issue a token and redirect to the returnurl
In my experience, idsrv3 is great, but it can be time-consuming to get things right when customizing and I would like to be sure that I don't hit a brick wall somewhere near the end of the solution.

Oauth2: authorize access based on unguessable url in email

Our application uses oauth2 & openid connect for auth&auth. It's built using an angular client that calls a REST API. I would like to know how to authorize access to the API, based on the possession of an unguessable url.
I'll explain this a little more. In the application, a user can invite another user. When this happens, an email is sent to the second user. When user 2 clicks a link in the email, he is sent to a webpage with details about the invitation.
Only user 2 should be allowed to see the invitation page. I was planning to solve this by using an 'unguessable url' in the email. Upon visiting the url, the user must somehow be authorized to fetch the invitation details from the API.
The question: how do I authorize a user, based on knowing the unguessable url? How do I assign a claim when the page is loaded, and how do I verify this claim in the API call that follows? The only solution I see, is to set a cookie containing a token. But this is not in line with our existing auth mechanism. I prefer not writing my own token validation code, and let the Identity Provider handle this.
Additional info: user 2 may or may not have an account in the system, and he may or may not be logged in. Neither should prevent the user from seeing the invitation details. In other words: a totally unknown user should be able to see the page. The knowledge of the url should be the only requirement.
Any solution to this problem? Or am I handling it all wrong?
After asking around, the general consensus is to NOT let the external auth mechanism take care of this, but to validate the link ourselves.
The solution is to turn the unguessable part of the url (the 'link id') in some kind of token, which can be validated upon calling the API. This is done by the API itself, not by the Identity Server.
Applied to the invitation issue: when an invitation is created, store the link id together with some info, i.e. what kind of access it allows (invitation access) and the id of the invitation. When the user calls the API to get the invitation, pass the link id for validation. Match the invitation id with the invitation id stored in the link, and if it doesn't, throw an error.

Rest APIs to support forgot password functionality which span to multiple steps

I have to develop a Rest API for forgot password functionality which span in three different workflow i.e.
First I need to verify user input for name, email and phone. If all are valid and belongs to that particular user, will send some security code to user's email and phone.
If first step is success. Need to capture security codes(from email and phone) provided by user and validate those.
If second step is success. Capture user's new password and send a request to save that new password.
Now I can create three different Rest APIs for above three steps and perform the task whatever required for that particular API.
If I am calling this forget password from a UI, in that case it will be responsibility of the UI client to take care of the sequence of the API's being get called to complete the whole process. But from API perspective user can skip the initial 2 API calls and directly call the 3rd API which save/overwrite the existing password with new password.
How can I enforce the sequence of steps(APIs) being called even if consumer of the API's is not a UI rather I am using it by some Rest browser client?
You should merge both second and third step.
Basically, we should receive the validation token with the new password request to confirm if it's a valid operation.
First step, the user request a "forgot password" operation and you send the token to his email/phone. You shouldn't send that information in the response of this request for security reasons.
Second step, the user introduce the token (or open an link with the token in the querystring, etc) and introduce the new password. The request that will go the API will contain both the token and the new password. If the token is valid for that user, you must update the password.

How does AntiForgeryToken work

I'm in trying to protect from CSRF and have two scenarious:
Doing POST from within another site and it fails when I enable AntiForgeryToken
I have tried from my "malicious" Javascript (running on another site) to first do GET of the page, parse it and extract RequestVerificationToken and then do a POST. This also fails but it is unclear to me why?
Can anyone please explain why?
Here's a good tutorial on CSRF:
http://youtu.be/vrjgD0azkCw
Here is the general gist: You are logged in to your bank's website. Your bank puts a cookie on your machine so it can authenticate you. Every time you make a request to (ie. load a page from) yourbank.com, the browser sends the cookie to the web server and the code on the web server checks the cookie to make sure you're authenticated. Great.
However, while the cookie hasn't yet expired, you check your mail and open an email from a Nigerian Prince telling you to click on a link. You click on it (who can resist) and instead of taking you to the page the Prince has described, the link takes you to this URL:
http://yourbank.com/transfer.aspx?amt=1000000&from=myAccount&to=princeAccount
Because you're already authenticated at your bank (through the cookie), it thinks you're actually asking to transfer the money, so it does it.
This is obviously a bit of a contrived example, but it gets the point across. More realistically, the link might submit a request that changes your email address on a forum website that you belong to or something, so that they can get access to it.
So NOW, on to answering your specific question:
One way to combat this (used by Ruby and .NET and others) is to include an anti-forgery-token. Basically, when you request a page, the server includes a hidden field with an encrypted value. And when you submit the form, the website looks at the cookie to make sure you're authenticated, but it also looks at the encrypted value that the browser sends and make sure it's valid. The encrypted token would realistically be a session id that your account is tied to. So the server sees the cookie, identifies you as user 123, and then checks the encrypted form field token, decrypts the value and makes sure that unencrypted value matches your session or user id or something. If it does, it knows to proceed.
The Nigerian prince who sent you the link won't know what your session id is, and even if he did, he wouldn't be able to encrypt it with the same key and algorithm that the website is using.
And there you have it. Thwarting Nigerian princes one anti-forgery-token at a time.
(Nothing against Nigeria or Nigerians here. I'm sure they're lovely people. It's just their princes sometimes behave a bit poorly.) :)
For security reasons, you cannot retrieve content from another domain using AJAX.
Therefore, other sites cannot get your token.