This question pertains to the Visual Studio generated code that you get when you open an ASP.NET MVC application in Visual Studio Community 2015 RC.
In this generated code, what is the purpose of the actions SendCode and VerifyCode on the AccountController?
I have read their code but the time investment it requires to read this code and look up the meaning of the functions called within these from the MSDN -- all of which I have done -- and then open their views to see what they do, and then look for references of where they're called -- is too much for the benefit. Microsoft left so many comments in this generated code elsewhere. They could have left a few comments explaining the workflow of these actions and told us where they're meant to be (and are currently) called from.
One big reason for confusion is: these actions aren't called or redirected to from anywhere else.
Anyway, my understanding is that they're there to ask a visitor who has just registered on the website with his email address, to verify his email address by requesting that he be sent a code.
But then in the source code for the SendCode action, there's this drop-down in the code that gets the registered two-factor authentication providers in the View (which I have only seen by reading the code. I haven't been able to run this action because it isn't called from anywhere and I don't know how to get to it with the right arguments).
This leads me to suspect that this has to do with two-factor authentication by email and/or phone.
But two-factor authentication by phone is already covered in the ManageController.AddPhone action and the ManagerController.EnableTwoFactorAuthentication, right?
It seems like one needs an old priest and a young priest to understand what's in the generated code.
Could someone please tell me what these two actions are for and where are they (supposed to be) called from? What's the entire workflow for these two actions?
I believe these methods are in place if you wish to implement signup validation logic. For example, a user signs up to your website and you require them to validate their information (usually email address) before approving their signup.
So the flow would be:
User signs up
System creates user but doesn't activate account yet
System sends email to user email with validation link (AccountController.SendCode())
User opens email
User clicks validation link which navigates to validation page on your website
Page validates user information (AccountController.CheckCode())
If validation is successful, account is activated
If validation is not successful, error message is displayed
I'm not sure if you've seen this post already but it outlines how you can implement something similar using SendGrid as your email provider.
the purpose of sendcode and verifycode is in case you want to leverage MFA (multi factor authentication). hence, after login, you would be redirected to send code where you decide whether to send a code via i.e. mobile or email and once the code is sent, you get to verify code to enter the code you requested to complete the process.
Related
I'm looking to add 2 factor login to my Silex app.
However, I'm having some road blocks on how to get this working correctly.
my biggest sticking point is having the firewall not fully log the user in and instead direct them to a page to confirm their identity.
I've thought about using Symfony Guard, but looking at the documentation, I didn't see anything that would let me prevent the user from being logged in.
I don't have any code yet, at this point, I'm just tying to design the flow and after I have a concrete execution plan, I was going to then begin writing code.
I remember reading a blog post about doing this in Sf2, but I cannot find it now. Here's the gist:
the login part is the usual one
create a listener for the controller event, and redirect to the 2FA controller unless the user has a role (ROLE_GOOGLE_AUTHENTICATED or similar) and unless the user is requesting that route
on that url render a form and check if it's a post, and if the code verifies add that role to the user
I'm sure you can adapt it for silex. You can also check the bundles that exist for Sf2 on how they work exactly.
My question is about the MVC Antiforgery system (described here).
Consider a simple app which posts todos to /Todo/Create. The corresponding action method has the ValidateAntiForgeryToken attribute. Consider the following client workflow:
User A logs on and goes to the page to create a todo, but doesn't do it yet.
User B (physically on the same computer) opens a new tab in the same browser, logs out of User A's account, logs in as User B. The browser then gets User B's validation cookie.
Some time later, User A switches back to their original tab and hits 'create' on the todo they were making.
In this scenario, the Antiforgery verification will not pass because the form token was meant for User A, while the validation cookie is for User B.
I'm sure there are valid security reasons for this behavior (e.g. a script on another site that manages to login as malicious user so that the 'todo' data is posted to their account instead), but it doesn't stop the above scenario happening for my legitimate users sometimes.
My questions are:
Is there a 'best practices' way to handle this scenario? Is it usually just a case of showing a custom error, telling them to reload the page and/or login again etc?
Is there any way to know when the out-of-the-box MVC Antiforgery system runs into this error? It seems to only ever throw the same kind of Exception (HttpAntiForgeryException). Would I need to revert to using/modifying their source?
I see two ways of handling it:
Use Javascript callback to the server before hitting a button to detect if the user is still logged in. If not - display him a message. It should be relatively easy to do this. But it requires one additional call, and little bit more time to execute your request.
One solution to avoid callbacks could be using html 5 localStorage (and you can support that on other browsers using modernizr, for example). It is shared between tabs. But I'm not sure if this approach is good. Additional research required.
Catch HttpAntiForgeryException on the server, check if the user is logged in. If the user is not logged in, display him a message.
Usually approach (1) is used. On banking websites they detect with JavaScript when you logged out in other browser tab.
I'm working on a project that uses sessions to manage the currently logged in user with a slight twist, there is no log in form on the actual application. Instead, another site will provide a button that should log in the user and redirect to their profile page.
For example, the customer is viewing their profile on Site A, the 3rd party application. From their profile on Site A they click on a button that should log them in to Site B and redirect to their profile on Site B, the site I'm building.
I'm a unfamiliar with the security concerns for a case like this. My initial thought is that if Site A POSTs via https the user's email address and password, then it should work just as if they were filling the form out on my site, Site B.
What security concerns am I missing here or will this just not work at all?
NOTE: The 3rd party site is basically out of my hands and I'll never convince that team to setup any sort of OAuth protocol, or at the very least its going to take unacceptably long. Plus, OAuth, at least with my understanding is method to accept requests from any number of 3rd parties. No other site except for SiteA will ever attempt to log people in.
This sounds like a typical application for an OAuth provider.
Get an overview and grasp the concept here: http://en.wikipedia.org/wiki/Oauth
There already exists OAuth Providers in Ruby, so you don't have to do everything by yourself: e.g. https://github.com/songkick/oauth2-provider.
But if you really wanna do this without, then I would let the other server generate a hash containing the users id (can be username, email, or database id), a random token, the current timestamp and then sign this using MessageVerifier. Then you can check on your server if the timestamp is within a certain range (some minutes) and if the message verifies (using the same key naturally). If so, then accept the user.
If the other site uses PHP, then you might have to rebuild the generate method in PHP. Find the source in Ruby here.
Let's imagine I have following scenario
User receives an email that there is a new item waiting for her
Clicks on a link and is able to either confirm or reject item (details skipped)
Can then access a list of all her items
The trick is that I would like to allow all this happen without user signing in but then limit access to other parts of the website (like sending an item to another user)
How I see it is that:
when user clicks a link she is signed in but only on tier 1 - with access only to confirm/reject action and read only to index of items (that's when Devise session is created)
when user wants to access other part of the website the sign in page is presented
when user comes to the website just by typing in the url http://example.com and wants to access own account she is asked to sign in.
after sign in session is "promoted" to tier which allows full access
after some time of inactivity session is downgraded to tier 1 for security reasons
My inspiration comes from how Amazon works - you can access in read-only most parts of the account but before performing any destructible actions you need to sign in.
Does anyone have any experience with such approach or can share some blog posts, etc?
I didn's find anything on SO and Google mostly returned things about two-factor auth which is not the case here.
I also understand that there are security concerns with links in email.
I have implemented a very similar behavior few months ago. I don't have very interesting resources to show you but I can explain a bit how you could organize or think about the problem to solve.
Description
For the problem you state, it looks like once you have identified a user, you have two different states you can give him:
limited access (perform certain actions, read most of the resources, etc)
full access (allows them to do anything they would normally do).
Having stated that, what you need to do is figure out in which cases you will give a user each access state (for example):
signing in with email token -> limited access
password -> full access
authentication_token -> full access
omniauth -> full access
After that, you will need to save this information in the user session. This should be done anytime the user is authenticated, as you will know what strategy was used to authenticate the user.
To know if a user can or cannot perform an action you will need two things, know what the user can do, and the current "access state". Depending on those you will decide wether the user is allowed or not to perform a certain action.
Whenever a user can't perform an action and is logged in with limited access you should bring him to the flow for verifying his crendetials. This flow is pretty simple, almost like a sign in but just with the password. Once you verify his crendetials you can upgrade his authorization to a full access one.
Implementation details
I recommend you to create a Authorization model which will represent the "access states" that I mentioned. This model will have to be serialized in the session so you should be able to build it from a simple structure and serialize it again into that structure. The simplest the better (a boolean flag, an array or maybe a hash). For the case mentioned, it looks like a boolean would do the job.
Regarding implementation details, I recommend you implementing this with a Warden after_atuhentication callback.
You could implement this with CanCan by creating you own Ability that would be built with an Authorization instance and a User instance.
I think you're confusing authorization and authentication. Devise is an authentication solution, meaning it handles the "proof me you are who you say you are" part. Authorization is the "Ok, I know who you are, now let's see what can you do". Devise doesn't provide an authorization system beyond the simple "logged/not logged". If you need a more complex authorization system, use an authorization gem. CanCan is very popular.
I've gotten a good number of OAuth logins working on my site now. My implementation is based on the WebSecurity classes with amends to the code to suit my needs (I pulled the WebSecurity source into mine).
However I'm now facing a new set of problems. In my application I have opted to make the user email address the login identifier of choice. It's naturally unique and suits this use case.
However, the OAuth "standards" strikes again.
Some providers will return your email address as "username" (Google) some will return the display name (Facebook). As it stands I see two options given my particular scenario:
Option 1
Pull even more framework source code into my solution until I can chase down where the OpenIdRelyingParty class is actually interacted with (via the DotNetOpenAuth.AspNet facade) and make addition information requests from the OpenID Providers.
Option 2
When a user first logs in using an OpenID provider I can display a kind of "complete registration" form that requests missing info based on the provider selected.*
Option 2 is the most immediate and probably the quickest to implement but also includes some code smells through having to do something different based on the provider selected.
Option 1 will take longer but will ultimately make things more future proof. I will need to perform richer interactions down the line so this also has an edge in that regard.
The more I get into the code it does seem that the WebSecurity class itself is actually very limiting as it hides lots of useful DotNetOpenAuth functionality in the name of making integration easier.
Andrew (the author of DNOA) has said that the Attribute Exchange stuff happens in the OpenIdRelyingParty class but I cannot see from the DotNetOpenAuth.AspNet source code where this class is used so I'm unsure of what source would need to be pulled into my code in order to enable the functionality I need.
Has anyone completely something similar?
AttributeExchange only applies to the OpenID Providers (Google and Yahoo!) and you can see the extension used in their respective source files.
I recommend against using email address as the username. Email addresses can be recycled (an account can expire or be closed/canceled and the email address can be reassigned to a new user). If this happens, your site based on email addresses would "give away" all the data of the old user to the new user. Massive privacy violation and lawsuit potentially happening there. Far better to use the Claimed Identifier for the OpenID cases, or the service provider-specific user id number in the OAuth cases, as the primary identifier in your user table. Certainly you may capture and display the email address everywhere on the web site where you would display a username so as far as the user knows that's the username -- it's just that internally you use something more precise than that.