OAuth Redirect URL - oauth

In OAuth 2 when you add your client you give it a redirect url.
e.g.
http://example.com
But when you request authorization for a user, you also pass back a redirect url as part of the request.
e.g.
authorize?response_type=code&client_id=CLIENT_ID&return_url=http%3A%2F%2Fexample.com%2Fsecure%2F&state=STATE
My question is basically, what is the point in storing the redirect url against the client? Is this just for security to make sure you ONLY redirect to the original website and not whatever is passed as part of the request?
In any case what I have found is that the return url parameter sent as part of the request isn't honoured e.g. http://example.com/secure and the redirect url saved against the client is always used... and therefore you don't get redirected to your original request but just the home page.
What should happen? And why do we have the return url twice?
Should it not just be the domain stored against the client and then the return url passed back is used and then the domain compared for security?

This is indeed a security measure so that responses are only sent to URLs that have explicitly been associated with a client at registration/administration time.
The client may register multiple Redirect URIs and in that case it is useful to use the redirect_uri query parameter in the request to indicate to which one of the registred values the server needs to send the response. In case there's only one registered value, the redirect_uri query parameter may be omitted from the request.
This mechanism secures against phishing attacks where an attacker phishes the user in to clicking a link that contains a crafted redirect_uri parameter that points to a domain/server that the attacker controls.
The spec allows indeed for registration of a pattern that can be used to match against the redirect_uri value in the request, so e.g. a domain wide policy can be configured. This is an option that is implementation specific. Note that in that case you need to be sure that all possible URLs/paths on the domain are in fact controlled by the client owner and noone else (e.g. that excludes pages that load content from foreign domains, or potential dangerous wiki/forum pages). Since that is pretty hard in real life, the recommended/default matching is very strict.

Related

How can be sure if a user is coming from a specified website in only one HTTP GET request?

I have 10 websites hosting in my IIS. A user clicks on a link in site 1, the secret value generated in server-side (of site 1), then I want to send this secret value (encrypt or hash) in URL (query string) to central site and decrypt/validate the value there, to be sure a user is coming from site 1 to proceed (and not from another websites).
I think it won't be something fixed string so users can make this URL themselves:
https://centralSite.com/process?param1=....&param2=....&source_website=site1
It should be something like a one-time dynamic generated token.
My question is :
Can I achieve this situation in only ONE HTTP GET request?
Should I use encryption/decryption or hashing/validating (all server-side)?
P.S: I can't use POST or other HTTP verbs here.
P.S: I know about HTTP referrer, but it can be spoofed or be null in some situations.
P.S: All websites are serving on HTTPS protocol.

Should dynamic query parameters be present in the Redirection URI for an OAuth2 (Autorization Code Grant Type)

Sources such as this Okta sponsored site (see "Per-Request Customization" section) mention that the redirect_uri parameter of a autorization request SHOULD NEVER have a dynamic query part (ex: for session matching uses).
Quote:
The server should reject any authorization requests with redirect URLs
that are not an exact match of a registered URL.
Our OAuth AZ provider is BIG-IP F5. We are setting it up, and they seem to comply with the above view.
Our client is a web application built elsewhere, and they seem to not follow the above rule.
Here is a complete representation of the Authorization Endpoint (redacted):
https://ourownF5host.ca/f5-oauth2/v1/authorize?client_id=theIDofOurClient&redirect_uri=https%3A%2F%2FourClientAppHostname%2FClientRessource%2FRessource%3FSessionId%3D76eab448-52d1-4adb-8eba-e9ec1b9432a3&state=2HY-MLB0ST34wQUPCyHM-A&scope=RessourceData&response_type=code
They use a redirect_uri with a format similar to (I don't urlencode here, for simplicity's sake) : redirect_uri=https://ourClientAppHostname/ClientRessource/Ressource?SessionId=SOMELONGSESSIONID, with the SOMELONGSESSIONID value being DIFFERENT for each call.
We dug DEEP into RFC6749 (OAuth2), and found this in section 3.1.2.2:
The authorization server SHOULD require the client to provide the
complete redirection URI (the client MAY use the "state" request
parameter to achieve per-request customization). If requiring the
registration of the complete redirection URI is not possible, the
authorization server SHOULD require the registration of the URI
scheme, authority, and path (allowing the client to dynamically vary
only the query component of the redirection URI when requesting
authorization).
What I understand, and would like to validate here, is that the first source, Okta and F5 accept ONLY the first part of the rule above, and require the redirection uri to be COMPLETELY registered without any dynamic part.
Am I right to affirm that they (Okta and F5) DO NOT comply with the second part of the excerpt, citing that they should "allow(ing) the client to dynamically vary
only the query component of the redirection URI when requesting
authorization" ?
OR, is there any kind of official correction/evolution of the RFC6749, that warrants both companies design position ?
TL;DR:
No, the redirect uri must be static for security reasons. If the client needs to keep a state between the authorization request and its asynchronous response, use the OAuth 2.0 state parameter.
Long version :
RFC6749 (the initial OAuth 2.0 specification) has been published in 2012 and OAuth security landscape has evolved a lot since then.
RFC6819, an OAuth 2.0 security review from 2013 already mentioned that refusing dynamically crafted redirect uris was a good way to protect against XSS and client impersonation attacks.
OpenID Connect, from 2014, a commonly used extension of OAuth 2.0 with authentication capabilities, already takes that recommendation into account and mandates exact string matching for all redirect uris.
The current draft recommendation for OAuth 2.0 Best Security Practice confirms that by enforcing redirect_uris preregistration and mandating the use simple string comparison by the AS when validating the redirect_uri passed in the request. So a dynamic redirect_uri must not be used.
Your client definitely makes a wrong move by using the redirect_uri as a "state keeper" between the Authorization request and response, by using a dynamically crafted SessionID attribute inside the redirect_uri. OAuth2.0 has a dedicated authorization request parameter for that purpose, which is "state". The client should use it. The AS will append that state in the parameters of the redirect_uri when it issues the response, so the client will be able to find back this state inside the response.
The proper authorization request would be:
https://youras/authorize?client_id=your_client_id&response_type=code&state=SOMELONGSTATE&redirect_uri=https%3A%2F%2Fsomehost%2Fauthcallback
The response will look like:
https://somehost/authcallback?state=SOMELONGSTATE&code=anazcode
This way the redirect_uri is static, so a simple string comparison is enough to validate that uri on AS side. Any algorithm more complex than simple string comparison would be subject to security flaws.
It appears there's two things mixed up here: the URL you refer to:
https://somehost/authcallback?state=SOMELONGSTATE&scope=someobjecttype&response_type=code
suggests that you mixed up the Redirect URI (aka. callback URL, as suggested by the pathname in the URL) of the Client with the Authorization Endpoint of the Authorization Server.
Only the Authorization Endpoint would take parameters as suggested and may contain e.g. a dynamic state value. The Redirect URI of the Client would not contain e.g. response type.
A redirect_uri parameter can be added to the the authorization request, which would then have to be matched in the way that you described. After confirming the match, the Authorization Server will redirect back to the Redirect URI, adding the code and state parameters.
Update (after the question changed):
OAuth 2.0 RFC6749 allows a dynamic (SessionId) parameter though it is not considered best practice. If however your client is an OpenID Connect Client, this is not allowed since the OpenID Connect spec (a "profile" of OAuth 2.0) locks down the Redirect URI matching to "exact", in which case you'd have to configure all possible SessionIds.

Linkedin OAuth2.0 : How to configure OAuth 2.0 Redirect URL with a wildcard subdomain url for a multi tenant application

I am trying to configure a LinkedIn application for a multi tenant site. I will have 20+ tenants using the same application and the number is going to increase every time.
As per Linkedin API documentation (https://developer.linkedin.com/docs/oauth2) we need to ensure following points
We strongly recommend using HTTPS whenever possible
URLs must be
absolute (e.g. "https://example.com/auth/callback", not
"/auth/callback")
URL arguments are ignored (i.e.
https://example.com/?id=1 is the same as https://example.com/)
URLs
cannot include #'s (i.e.
"https://example.com/auth/callback#linkedin" is invalid)
Can i configure redirect url as https://*.mysite.com/auth/linkedin/callback instead of specifying url of each tenant separately.
You cannot do a subdomain based wild card mapping as the IP should know the RP.
You can change the logic after you get the authorization callback, so you set the cookie and then you will have to redirect the user back to the tenant URL instead of the base URL.
Anyway, after successful authorization, you will be redirecting the user to an action, just figure out the subdomaina and the construct the URL and do the redirection
HTH
EDIT
Since the use of the URL or other approaches seem to be a hack, can you please try to have a facade like application (or Gateway like one) that has a URL that is registered in linkedin and then on receiving the response, it can use a state or other factor to redirect to the tenant URL. This can use a 302 and it will be invisible unless the user is on a very slow network. This approach does not require any hack like approach.
Here state can be a function that takes a tenant info and generates a dynamic hash that is stored for tracking and redirection.

Does RedirectToAction pose a security risk?

I have an HTTPS post coming in via a secure form. Without going into lengthy explanation: I need to call an action within the same controller that accepts two tokens passed as parameters. When I run Fiddler, I see that that method is being called with the parameters in the URL. My question is: Does this pose a security risk? Is there a more secure way of redirecting within the same controller?
Yes, it poses a security risk, but it is easily mitigated by simply validating that the urls you are redirecting to are within the same domain as your source destination.
In fact, this is on the OWASP top 10.
A10 - Unvalidated Redirects and Forwards
EDIT:
I just realized that I missed the "ToAction" part of the question, so no.. It's not really possible to redirect outside of the site with RedirectToAction, so there isn't a worry for that. However, if you are using direct user input to feed into your RedirectToAction (and that includes accepting post data that you generate in a different page) then it's possible that an attacker could redirect to a method you did not anticipate. However, this is no different from a user simply trying random URL's and hitting one, or knowing a url and going to it manually. You need to have authorization in place to prevent access to URL's that the user does not have authorization to view.
If the original Action is accessed via HTTPS then RedirectToAction will redirect to a relative URL on the same domain using the same protocol.
So if your original page is
https://www.example.com/Foo/Bar
and this redirects to the FooBar action with some route parameters:
https://www.example.com/Foo/FooBar/1/2/3
an attacker cannot read the parameters 1/2/3 nor the rest of the URL.
However, the things you should bear in mind are:
The URL parameters will be logged by default by the browser (history), your server, by corporate proxy servers and possibly by other devices on your network by default.
If the user follows any links from your page to other https URLs, the referer HTTP header will contain your page address including parameters. Modern browsers will not send the referer header with http links though.
If there are any other https resources on your page this will cause the browser to send the referer header with the request.
For these reasons, if your parameters (1/2/3) are private, then you may wish to POST this data to the target page rather than use RedirectToAction (which results in a GET).
Note that you should be validating that the current user has access to the resources that 1/2/3 refers to (e.g. if the parameters were an order ID, you should check that the user identified by their auth cookies allow them to see the order referenced). Keeping 1/2/3 private are only beneficial if the parameters are themselves sensitive (e.g. a social security number).
Note that the OWASP Top 10 vulnerability, "A10 - Unvalidated Redirects and Forwards" does not apply here as RedirectToAction can only redirect to another action. If the other action redirects to a user set URL, then the vulnerability would lie there instead.

ASP.NET MVC ValidateAntiForgeryToken — can it be replaced with authorization check & referrer check?

In ASP.NET MVC there is a ValidateAntiForgeryToken attribute, that enables cross-site scripting defence.
Is it possible to replace this mechanism with
authorization check, including checking that resource, that is being manipulated, belongs to current user;
referrer check, that will forbid AJAX web api requests from external hosts;
inhibition of site hosted in iframe?
This does not prevent cross site scripting, only cross site request forgery.
authorization check, including checking that resource, that is being manipulated, belongs to current user;
No, because the resource does belong to the current user, it is only the request that has not been willingly made by the current user.
e.g. say on your website www.foo.com you have the following URL that will delete the user's account.
www.foo.com/DeleteAccount
Your user is logged into www.foo.com. Now say your user visits www.evil.com which includes the following image tag on the page.
<img src="http://www.foo.com/DeleteAccount" />
This will make a request to your page and delete the user's account because the DeleteAccount resource will have checked authorisation via cookies and determined that the user is indeed authorised because the auth cookie was supplied with the request.
referrer check, that will forbid AJAX web api requests from external hosts;
Yes, this is a valid check although it is weaker than the method of using the Anti Forgery Token as mentioned in your question.
The OWASP CSRF Cheat Sheet states
Although it is trivial to spoof the referer header on your own browser, it is impossible to do so in a CSRF attack. Checking the referer is a commonly used method of preventing CSRF on embedded network devices because it does not require a per-user state. This makes a referer a useful method of CSRF prevention when memory is scarce. This method of CSRF mitigation is also commonly used with unauthenticated requests, such as requests made prior to establishing a session state which is required to keep track of a synchronization token.
However, checking the referer is considered to be a weaker from of CSRF protection. For example, open redirect vulnerabilities can be used to exploit GET-based requests that are protected with a referer check. It should be noted that GET requests should never incur a state change as this is a violation of the HTTP specification.
There are also common implementation mistakes with referer checks. For example if the CSRF attack originates from an HTTPS domain then the referer will be omitted. In this case the lack of a referer should be considered to be an attack when the request is performing a state change. Also note that the attacker has limited influence over the referer. For example, if the victim's domain is "site.com" then an attacker have the CSRF exploit originate from "site.com.attacker.com" which may fool a broken referer check implementation. XSS can be used to bypass a referer check.
Also note that sometimes the referer isn't always passed as the user may be using privacy software that removes the header.
inhibition of site hosted in iframe?
This can be a valid defence for widgets that you host to be included on other sites.
e.g. www.bar.com could include your widget on their page via the use of a script tag:
<script src="//www.foo.com/widget.js"></script>
In order to prevent www.bar.com from submitting the form within your widget, your JavaScript code would document.write an IFrame into the page and then include your content within that. The Same Origin Policy will prevent the IFrame content from being read by the parent page and your form could not then be submitted by the site that includes your widget. However, here you may need a manual confirmation window to pop up in the case of any clicks to prevent click jacking attacks (e.g. if you had a like button (similar to Facebook) and you wanted to prevent fake likes from the including page submitting your form automatically).
OWASP Recommendation
The OWASP Recommendation is to use the Synchronizer Token Pattern which is the one implemented by ASP.NET MVC with ValidateAntiForgeryToken.

Resources