I am storing response from openid provider using
NameValueCollection query = HttpContext.Current.Request.QueryString;
I am sending request for emailid as
"&openid.ax.type.email=" +
HttpUtility.UrlEncode("http://schema.openid.net/contact/email"))
but receiving emailid in openid.ext1.value.email in some case and openid.ax.value.email in others.
There is a similar question, which I answered.
You must check everything starting with "openid.ns." and search for the correct namespace.
You can't depend on it being ax, ext1, or anything else.
Additionally, you can't depend on the name being "email", you still have to check what it's named by checking namespaces in openid.ax.type. (where ax can be any alias, see above)
Related
The background first:
I have an application where a logged-in user(employee) X can see a list of all other users (employees). If the logged-in user X is a manager (their designation), then they can also edit certain attributes of the users they manage. For example, the location, designation, and the department of the user being edited. It should be noted X can edit only those employees who report to him/her, which means there are users which X is not allowed to edit.
When X clicks on a user to edit it, they navigate to a page like http:myapp.com/dashboard/editUser/<ID_OF_THE_USER_BEING_EDITED>
Obviously, X can get smart and manually edit the URL and put in the id of a user they are NOT allowed to edit, so before loading the edit form I need to check whether X has the authorization to edit user Y.
if X is authorized to do so, then that page displays a form (with the current attributes of the users pre-filled in the appropriate fields) to edit the user. Else, I display an 'Access Denied' kind of message.
Right now I have created a very badly named temporary endpoint (/api/v1/maybe_edit_user/?jwt=<TOKEN>&userId=<USER_BEING_EDITED>).
This grotesque-looking endpoint does 2 things:
It extracts the currently logged-in user from the token, and checks whether it has the required access level to edit the user (passed through the GET parameter userId)
If yes, then it returns the current attributes (name, email, location, designation, and other stuff) in the response, which is then pre-filled in appropriate fields when the form is displayed.
Once X submits the form, a PUT request is sent to another endpoint (/api/v1/users/<USER_ID_OF_Y> PUT) and the user Y is updated.
While this works, I don't find it attractive. I am trying to learn to write better, cleaner, and more organized code that is compliant with the standards.
The best practices for REST suggest that all endpoints should be nouns. My endpoint, on the other hand, is not even a simple verb. It's a god-forsaken phrase at the very minimum.
So, the questions here are:
How should I name my endpoint.
Should I use a single endpoint to check for permission, AND fetching the attributes of the user being edited, like I am doing right now? Or should I break them into 2 separate endpoints?
The fact that there is an access control list is an unrelated concern; ignore it.
Resource identifier identify resources. Resources are generalizations of documents.
You want an identifier that is consistent with the production rules of RFC 3986, and it is often convenient (but not required) to choose spellings that enable leverage of URI Templates (RFC 6570), but otherwise the machines don't care.
That means you can choose a spelling that makes things easier for humans; you get to choose which humans get priority here.
it returns the current attributes (name, email, location, designation, and other stuff) in the response
That's your hint as to what the document is; some sort of digest of Bob's... profile? employee record? dossier? that is apparently optimized for use in this specific kind of form.
So the identifier could be as simple as
/this-specific-kind-of-form/source-data/Bob
and a request might look like
GET /this-specific-kind-of-form/source-data/Bob HTTP/1.1
Authorization: Bearer <token>
The implementation looks largely like your sketch - verify the token, compare the claims to those that are required, and return either the resource or some flavor of Client Error (4xx).
The best practices for REST suggest that all endpoints should be nouns.
Don't read too much into that.
Notice that all of the following resource identifiers work:
https://www.merriam-webster.com/dictionary/get
https://www.merriam-webster.com/dictionary/post
https://www.merriam-webster.com/dictionary/put
https://www.merriam-webster.com/dictionary/patch
https://www.merriam-webster.com/dictionary/delete
You can click on any of those links, and your browser will create the correct HTTP request, and the server will do the expected thing.
I am using spring validation:
#NotNull
#Size(max = 128, min = 6)
#Email
private String username;
But I want to ensure that the new TLDs are respected. Does spring even look at the email domain TLDs and ensure they are adhered to?
Just to give an example: I want the following to validate: joe#emperor.clothing
What exactly are you after? What do you mean with:
But I want to ensure that the new TLDs are respected
#Email is Hibernate Validator provided Bean Validation constraint which will verify whether a given email adheres syntactically RFC 2822. It does so via a regular expression.
The javadocs of EmailValidator says:
The specification of a valid email can be found in RFC 2822 and one
can come up with a regular expression matching all valid email
addresses as per specification. However, as this article discusses it
is not necessarily practical to implement a 100% compliant email
validator. This implementation is a trade-off trying to match most
email while ignoring for example emails with double quotes or
comments.
This also means, that there is no internet connection established to for example verify whether a top level domain actually exists (in case that is what you mean).
I'm using the Authorization header with the Basic type for authentication.
I'm following the HTTP Basic authentication specifications which states that the credentials should follow this form -> userIdentifier:password encoded in base64
We are using an email as the user identifier and according to the email format specification, the colon(':') character is permitted.
The colon(':') is also a valid character in the password.
Knowing this, I'm looking for a creative way to parse the credentials part of the header that uses a colon(':') as the separator between userID and password.
In this case it's simple -> francis#gmail.com:myPassword
This is where it gets complicated -> francis#gmail.com:80:myPasswordWith:Inside
francis#gmail.com:80 is a valid email according to the email format specification even though this is not used very often. So where do I know where to split ?
We have made the decision not to accept an email containing a ':'. But we want to notify the user that his email is not valid, how can we ensure that we are splitting the string at the right place ?
Hope I asked my question in a clear manner, don't hesitate to ask for more details
Thank you
Don’t notify the user that the email is invalid. Split according to the RFC 2617 rules (everything after the first colon is the password), then try to authenticate, fail, and return a generic “authentication failure” message.
A situation where john#example.org:80 has password secret and john#example.org has password 80:secret at the same time, seems unrealistic.
If you require your users to register, you probably do it with some other mechanism (forms?) where you can easily separate the username and tell that it is invalid.
I'm working on an asset management website where in whenever an asset is issued to a user the system would send an email notification with a url in it that would show the user all the assets issued to him. I could have used the query string to pass the user ID but again people could abuse it to view assets issued to other users. My client doesn't wants the user to authenticate themselves when they click on the link. So i need something that would hide the parameters being passed in the query string or at least make them obscure. I've read about url encoding, GUID etc. but i'm not sure what to do. I'm just a beginner. Please pardon my ignorance and point me in the right direction.
Taken what you have said, that you're just a beginner, and assuming that this will be public, you can do the easiest way:
Create a new table in your database and called for example tbl_links, as columns just add 3
user_id (foreigner key to the user table)
guid (primary key, unique)
settings (nvarchar(250)
When you need to send an email, create a new row for the user, for example:
Guid guid = Guid.New();
String settings = "date_from:2012/01/01;date_to:2013/01/01";
And insert it one the database, where the link that you put in the email, should have the guid, for example, http://domain.com/info/?g=....
You could append Json to that settings column and parse it into an object again in the code, ask a new question if you want to take this route.
I personally use a security algorithm to pass only the user_id but you did said you're a beginner, so I only showed you the easy and still valid way.
P.S. for security reasons, you should say in the email that your link is only valid for the next 4 hours or so you can prevent people from generating GUIDs in order to try and get some information.... Simple add a create_date column of type datetime and use that to see if the link already expired or not...
For obscuring URL parameters, you want to use a modified Base64 encoding. Please keep in mind that obscurity is not security, and Base64 encoding something does not in any way make anything secure.
If you're intending to use this for authentication purposes, I think you should reconsider. Look into public key encryption and digital signatures as a starting point.
Trying to secure access to a URL is not the right approach. Give the urls away freely and authenticate your users instead.
I would also highly recommend using SSL for serving up this data.
Security through obscurity fails 100% of the time once the obscurity is not longer obscure.
What you can do is to add some prefix and suffix to the id and the encrypt that string. Something like this:
static public string EncodeTo64(string toEncode)
{
byte[] toEncodeAsBytes
= System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
string returnValue
= System.Convert.ToBase64String(toEncodeAsBytes);
return returnValue;
}
static public string DecodeFrom64(string encodedData)
{
byte[] encodedDataAsBytes
= System.Convert.FromBase64String(encodedData);
string returnValue =
System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
return returnValue;
}
string prefix = "lhdsjñsdgñdfj";
string suffix = "dfknsfñn3ih";
var strToEncode = prefix + "|" + id + "|" + suffix;
var encoded = EncodeTo64(str);
var decoded = DecodeFrom64(encoded).Split('|');
if( decoded.length != 3 || decoded[0] != prefix || decoded[2] != suffix )
throw new InvalidArgumentException("id");
var decodedId = decoded[1];
I have the user controls (ASP.NET 3.5) implemented and noticed that each user is given a UserProfileID
I'm implementing a public page for each user, as asked and answered here, that will use the UserProfileID in the URL.
My question is, can the UserProfileID be used maliciously? Is it OK that anyone can see that persons UserProfileID ?
Is it OK to have something like that in the URL?
(Also, the userIDs are very long, i.e. - a051fc1b-4f51-485b-a07d-0f378528974e
Is there a way to shorten what each user's unique URL is? )
The answer to your first question is no, there aren't really any security issues posed by exposing a user's id in the URL (as long as you have other means of authorization - don't use that id in the URL to authorize the user).
To answer your second question, the id is a GUID which is quite long. If you wanted something shorter you would have to store your UserProfile object with a different type as the key in the data store (like an integer which would be shorter).