There's a subset of users which will not have access to the system I'm implementing in the beginning but I need a mechanism for them to capture data for one specific part of the process.
An authorized user creates the original record for a Person with some basic details i.e. First name, last name etc.
I then create a 'DataRequest' record which has a unique guid and the external user is sent an email with a path which is effectively http://sampleapplication/Person/Complete?guid=xxxx
The external user adds additional details like Date of Birth, Eye colour etc, submits and saves to the DB. The DataRequest for that guid is then expired and cannot be accessed again.
The Complete action doesn't have any authorization as these external users do not have user accounts.
My preference is to force these users to use the system but at this stage I'm not sure it's practical.
Is this a bad practice?
Should I be implementing some additional security on this like a one time password / passcode contained in the email? Are there alternative approaches I should consider?
There's nothing wrong with opening up a section of your site to the public. Tons of websites have secured and unsecured sections. However, there's also nothing saying that you have to expose your secure site at all. You can create another site that merely has access to that change those records and make that site alone, public.
As far as securing the information of the user, passcodes by email are the invention of some developer somewhere with limited mental ability or a severe lack of sleep. If the link is only available by email (not discoverable by search engines and not easily guessable), then anyone with the link will also have the passcode, making the passcode to access the link redundant.
You should however log when the email is used to finish the record and then disallow further uses.
Related
I'm learning about Google OAuth, and it says that my project has no appropriate credentials.
So I go to the Developers Console and click on the OAuth consent screen. I type my domain name into their question:
Authorized domains To protect you and your users, Google only allows
applications that authenticate using OAuth to use Authorized Domains.
Your applications' links must be hosted on Authorized Domains.
I have verified my domain, but I get "Must be a top private domain." The link takes me to some kind of java programming statement. Actually if I click on the Domain verification tab (again) there are no domain names listed, but I know I added it.
Q: How do I add my domain for being used with OAuth? Must I qualify it as a Top Private Domain or am I going down a rabbit hole?
Google oauth requires a top level domain for security purposes. A top level domain is the first one before the .com .net .biz, in other words it only has one dot. There are exceptions such as .co.uk.
Subdomains are controlled by the parent domains and are not necessarily owned or controlled by you. Imagine you have a Wordpress account at domain.wordpress.com. Wordpress closes your account and returns domain to inactive. A different user claims the domain user and domain.wordpress.com. If Google allowed subdomains they would be forced to believe the new user was you. (Since there is no requirement of public notification of the change)
Edit (a more generalized statement in response to a comment.)
If you own the domain, you have full control over it, and the ownership records are public. To prove your virtual identity as owner of the domain when subscribing to many services require a DNS record, that is created by you, as a challenge created by the provider, that can be read by the provider, prior to services being created. In the event of a change in ownership the original claimant, you, is sent a new record to the provided email address to add to your DNS server to prove you still own the domain. If you cannot prove you still maintain ownership of the name, as in the case of an expired domain hijack, all services are canceled.
Edit
The most probable problem is: Your domain verification is failing.
Start the verification process again. This will give you a new TXT record to add to your DNS.
Go to your DNS providers page and add the record. While there look for the refresh value on the SOA record.
Convert the SOA refresh from seconds to hours. Divide by 3600.
Wait that amount of time + 4 hours for replication.
Use nslookup (or dig) and look for the TXT record. Be sure to use Google's DNS server at 8.8.8.8(server=8.8.8.8).
If the record is not found, wait some more, if (hours waiting > 72) break; else repeat check.
If nslookup was able to find the record, complete the verification process; if not contact your DNS provider(The client record hold can be an issue).
If at this point everything went well, You should have an authorized domain.
If not (domain disappears, contact Google support), It my have to do with the privacy settings on the domain. Most quote public domains have contact information.
You must use a TLD (top level domain). If you have a subdomain, it is owned by the person who owns the TLD. For example, you might have a blog at myamazingblog.wordpress.com, and wanted to use OAuth with it. Unfortunately, this would not be possible, since you do not own wordpress.com (the TLD).
Try testing on a different device or clearing cache.
For me it turned out I had everything correct (just with my example.com domain) but my iOS safari was caching something and it kept giving me the ‘not whitelisted’ message. Which led me to think I needed to add dev.example.com as well - which isn’t necessary.
So try going to the site on another device or browser to see if it works.
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.
I am designing a website for a client to sell their services. Basically my client simply wants customers to book slots in appointments diary via paypal and be able to manage their bookings. My strategy is simple registration using email address and generating a 10 digit random booking reference which I will use as a password so that the users find it convenient to use the site (get rid of registration and other stuff). My question is there any security issue if I display the password after a client has made a booking? or should I do it like 4chan i.e just enter email address and password yourself?
Remember that everything you show or send to the user can be read by others. I wouldn't use your approach, but it depends on the purpose of the application and what a (malicious) user can do in your system (e.g. is it read only or can he make changes in bookings?).
In any case I would secure the website with an SSL certificate (which is probably enforced by law as well since you're dealing with personal data).
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.