redirect_uri_mismatch with https-only app on AppHarbor - asp.net-mvc

I've deployed MVC 5 site to AppHarbor, got the https-only app working thanks to this gist linked by AppHarbor support.
When I connected to Google OAuth 2 provider locally, everything worked fine - I can log in without problems, but when I try it on AppHarbor, I get error on login "redirect_uri_mismatch". I've got proper key and secret set for web app, the problem is with path, for some reason my page responds with redirect_uri starting with "http://..." instead of "https://..." which I've set in the google project console - (other than that it's the same uri).
I've tried this workaround for URL-based problems, but it doesn't seem to change anything.
As I don't think switching to http for /signin-google would be a good idea - how to fix it?

It's a few months later but I hope this will help someone. I had exactly the same problem with AppHarbor load balancers and loosing the "https" in the redirect_uri string. The simplest solution that I found is to register a few lines of code like a middleware in Startup.Auth.cs before any registration of external login providers:
app.Use(async (context, next) =>
{
if (string.Equals(context.Request.Headers["X-Forwarded-Proto"], "https", StringComparison.InvariantCultureIgnoreCase))
{
context.Request.Scheme = "https";
}
await next.Invoke();
});
This simple middleware checks for AppHarbor header "X-Forwarded-Proto" and if exist just add a correct Scheme property. If you look at the Katana's code correct Scheme property solve the problem:
...
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
...

Related

Azure AD Ms Identity callback URL (error AADSTS50011)

I'm integrating Azure AD and MS-Identity on a web app with Angular.
It works on my machine, but when I deploy it, I get an issue with the callback URL.
First, to make sure the callback URL is ok, I extract it from the microsoft login popup window's URL:
Then, I url decode the content. The URL seems fine and it is available in my Azure app's redirect URL.
Then I login to Microsoft normally and I get this error (AADSTS50011):
Then I inspect the URL again (inside the query string from the urldecoded popup window's URL) and now the URL seems to have been "tampered with".
It's now something like this:
http://somedomain:80/some_page/somequerystring
instead of
https://somedomain/some_page/somequerystring
so I wonder if it's part of the problem or if it's normal behavior.
It is also mentionned "If you contact your administrator, send this info to them." I suppose I'm the "administrator" so what can I do with that "Copy info to clipboard" info to investigate the problem?
Is your application hosting on http (80) or https (443)? If your app service is terminating your TLS connection and handling that for you instead of your app, your sign-on will construct the redirect using the http request scheme. I hooked into the OnRedirectToIdentityProvider event to correct the scheme.
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
Configuration.Bind("AzureAd", options);
options.Events ??= new OpenIdConnectEvents();
options.Events.OnRedirectToIdentityProvider += _fixRedirect;
});
...
private async Task _fixRedirect(RedirectContext context)
{
context.Request.Scheme = "https";
if(!context.ProtocolMessage.RedirectUri.StartsWith("https"))
context.ProtocolMessage.RedirectUri =
context.ProtocolMessage.RedirectUri.Replace("http", "https");
await Task.CompletedTask;
}

spring security sasl: Unable to configure SSO url

I am using following spring security saml repo from github:
https://github.com/spring-projects/spring-security-saml/tree/master/sample
Whenever I try to update the SSO url, for e.g. localhost:8100/saml/ddo, instead of /saml/sso, browser gets stuck in infinite loops.
(I have followed the steps mentioned in readme and updated the url on okta as well in application to test)
Sample code and config enclosed in:
Spring secuirty saml issue
EDIT:
I did what below answer suggested,but I am getting the Incoming SAML message is invalid..
On debugging, I found that attemptAuthentication in SAMLProcessingFilter, the location in endpoint that are added still contain the /api/saml/SSO instead of /api/saml/ddo
and that's why getEndpoint method in SamlUtil throws excpetion with following line:
throw new SAMLException("Endpoint with message binding " + messageBinding + " and URL " + requestURL + " wasn't found in local metadata");
because the requestUrl and endpoint location do not match.
I also checked my metadata.xml but it does not contain any info related to these urls.
In the MetaDataGenerator class method getSAMLWebSSOProcessingFilterPath, the samlWebSSOFilter is null and that's why the default filter url: /saml/SSO is returned. I am trying to figure out how to set this value at runtime?
I understand that there is a method with name: setSamlWebSSOFilter, and everything works correct if I provide the url /saml/ddo at the time of startup. But I am not able to make this work if config is changed at runtime.
Any idea how can I move forward?
Setting field filterProcessesUrl on bean samlWebSSOProcessingFilter to value /saml/ddo should solve the problem.

Identity Server Endpoints OIDC

I am using Identity server and hosting it under IIS. It was working fine when hosted directly under http://localhost:44431
Step 1: call http://localhost:44431/account/login?returnUrl=/connect/authorize/login?respone_type....
Step 2: Then it goes to the Authorize Endpoint and a return a token
Probelm hosting under localhost\id:
However, when I deploy the application on IIS under Default Web site as localhost\id. It stops working.
Step 1: Calling http://localhost/id/account/login?returnUrl=/connect/authorize/login?respone_type....
>> Inspecting the Request Headers:
>> Response Header:
>> Open Id Configuration at http://localhost/id/.well-known/openid-configuration
"authorization_endpoint":"http://localhost/id/connect/authorize",
Step 2: Calling the /connect/authorize endpoint:
>> Inspecting the Headers:
It didn't include the id virtual directory, that's why it is failing. where in the process I have to fix this?
I'm not able to reproduce your problem, but I did start from scratch hosting IdentityServer4 in IIS. The steps I followed for setup are below.
Cloned IdentityServer4.Samples. Launch Quickstarts/3_ImplicitFlowAuthentication solution:
https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/3_ImplicitFlowAuthentication
Created an application in IIS with the path as '/id' with the AppPool set to 'No Managed Code'
Ran 'dotnet publish' on the IdentityServer4 project and moved the output to the IIS app root's folder
Changed the Authority URL in the MvcClient project to point to localhost/id
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "http://localhost/id",
RequireHttpsMetadata = false,
ClientId = "mvc",
SaveTokens = true
});
Load the MvcClient application and navigate to a route with the 'Authorize' filter. The redirect occurred properly with the appropriate virtual directory
Check to see if the proper path is being output by IdentityServer by going to the openid-configuration page: http://localhost/id/.well-known/openid-configuration
Are you running IdentityServer4 and an MVC app in the same project? If so, are you using relative paths for the OpenIdConnectOptions.Authority property? Try changing it to an absolute path and see if that fixes the problem. I'm thinking this might be the case, because your request URL does not include the /id path in the redirect uri:
http://localhost/id/account/login?**returnUrl=/connect/authorize/login**?respone_type
The correct path of course should be:
http://localhost/id/account/login?**returnUrl=/id/connect/authorize/login**?respone_type
Hope this helps! Please let me know

Google+ api with dart chrome app - 403 Daily Limit

I am trying to use the google_plus_v1_api + google_oauth2_client within a chrome packaged app.
Everythin works fine when i am using only the oauth2 lib:
chrome.identity.getAuthToken(new chrome.TokenDetails(interactive:true))
.then((token){
OAuth2 auth = new SimpleOAuth2(token);
var request = new HttpRequest();
request.onLoad.listen((d){print(request.response);
request.open('GET', 'https://www.googleapis.com/plus/v1/people/me');
auth.authenticate(request).then((request) => request.send());
});
But i can't make google+ lib works:
chrome.identity.getAuthToken(new chrome.TokenDetails(interactive:true))
.then((token){
OAuth2 auth = new SimpleOAuth2(token);
Plus plus = new Plus(auth);
plus.people.get('me').then((d)=>print(d));
});
Return this exception:
GET https://www.googleapis.com/plus/v1/people/me 403 (Forbidden)
Exception: APIRequestException: 403 Daily Limit for Unauthenticated
Use Exceeded. Continued use requires signup.
Am i missing something? How am i supposed to use google+ api lib?
I just saw your answer, but wanted to point out I had the same problem and solved it by setting the makeAuthRequests property of the Plus client to true:
final plusclient.Plus plus = new plusclient.Plus(auth)
..makeAuthRequests = true;
Seems like a more straightfoward solution, since the auth object already contains the token. I would've expected makeAuthRequests to be automatically set to true when constructing a Plus client with an OAuth2 object, but apparently it's not (probably an oversight).
Sorry, i figured out that this line was missing thanks to this tutorial :
plus.oauth_token = auth.token.data;
My google_plus_v1_api query is now working.
Sorry for the inconvenience.

Twitter oAuth callbackUrl - localhost development

Is anyone else having a difficult time getting Twitters oAuth's callback URL to hit their localhost development environment.
Apparently it has been disabled recently. http://code.google.com/p/twitter-api/issues/detail?id=534#c1
Does anyone have a workaround. I don't really want to stop my development
Alternative 1.
Set up your .hosts (Windows) or etc/hosts file to point a live domain to your localhost IP. such as:
127.0.0.1 xyz.example
where xyz.example is your real domain.
Alternative 2.
Also, the article gives the tip to alternatively use a URL shortener service. Shorten your local URL and provide the result as callback.
Alternative 3.
Furthermore, it seems that it works to provide for example http://127.0.0.1:8080 as callback to Twitter, instead of http://localhost:8080.
I just had to do this last week. Apparently localhost doesn't work but 127.0.0.1 does Go figure.
This of course assumes that you are registering two apps with Twitter, one for your live www.mysite.example and another for 127.0.0.1.
Just put http://127.0.0.1:xxxx/ as the callback URL, where xxxx is the port for your framework
Yes, it was disabled because of the recent security issue that was found in OAuth. The only solution for now is to create two OAuth applications - one for production and one for development. In the development application you set your localhost callback URL instead of the live one.
Callback URL edited
http://localhost:8585/logintwitter.aspx
Convert to
http://127.0.0.1:8585/logintwitter.aspx
This is how i did it:
Registered Callback URL:
http://127.0.0.1/Callback.aspx
OAuthTokenResponse authorizationTokens =
OAuthUtility.GetRequestToken(ConfigSettings.getConsumerKey(),
ConfigSettings.getConsumerSecret(),
"http://127.0.0.1:1066/Twitter/Callback.aspx");
ConfigSettings:
public static class ConfigSettings
{
public static String getConsumerKey()
{
return System.Configuration.ConfigurationManager.AppSettings["ConsumerKey"].ToString();
}
public static String getConsumerSecret()
{
return System.Configuration.ConfigurationManager.AppSettings["ConsumerSecret"].ToString();
}
}
Web.config:
<appSettings>
<add key="ConsumerKey" value="xxxxxxxxxxxxxxxxxxxx"/>
<add key="ConsumerSecret" value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/>
</appSettings>
Make sure you set the property 'use dynamic ports' of you project to 'false' and enter a static port number instead. (I used 1066).
I hope this helps!
Use http://smackaho.st
What it does is a simple DNS association to 127.0.0.1 which allows you to bypass the filters on localhost or 127.0.0.1 :
smackaho.st. 28800 IN A 127.0.0.1
So if you click on the link, it will display you what you have on your local webserver (and if you don't have one, you'll get a 404). You can of course set it to any page/port you want :
http://smackaho.st:54878/twitter/callback
I was working with Twitter callback url on my localhost. If you are not sure how to create a virtual host ( this is important ) use Ampps. He is really cool and easy. In a few steps you have your own virtual host and then every url will work on it. For example:
download and install ampps
Add new domain. ( here you can set for example twitter.local) that means your virtual host will be http://twitter.local and it will work after step 3.
I am working on Win so go under to your host file -> C:\Windows\System32\Drivers\etc\hosts and add line: 127.0.0.1 twitter.local
Restart your Ampps and you can use your callback. You can specify any url, even if you are using some framework MVC or you have htaccess url rewrite.
Hope This Help!
Cheers.
Seems nowadays http://127.0.0.1 also stopped working.
A simple solution is to use http://localtest.me instead of http://localhost it is always pointing to 127.0.0.1 And you can even add any arbitrary subdomain to it, and it will still point to 127.0.0.1
See Website
When I develop locally, I always set up a locally hosted dev name that reflects the project I'm working on. I set this up in xampp through xampp\apache\conf\extra\httpd-vhosts.conf and then also in \Windows\System32\drivers\etc\hosts.
So if I am setting up a local dev site for example.com, I would set it up as example.dev in those two files.
Short Answer: Once this is set up properly, you can simply treat this url (http://example.dev) as if it were live (rather than local) as you set up your Twitter Application.
A similar answer was given here: https://dev.twitter.com/discussions/5749
Direct Quote (emphasis added):
You can provide any valid URL with a domain name we recognize on the
application details page. OAuth 1.0a requires you to send a
oauth_callback value on the request token step of the flow and we'll
accept a dynamic locahost-based callback on that step.
This worked like a charm for me. Hope this helps.
It can be done very conveniently with Fiddler:
Open menu Tools > HOSTS...
Insert a line like 127.0.0.1 your-production-domain.com, make sure that "Enable remapping of requests..." is checked. Don't forget to press Save.
If access to your real production server is needed, simply exit Fiddler or disable remapping.
Starting Fiddler again will turn on remapping (if it is checked).
A pleasant bonus is that you can specify a custom port, like this:
127.0.0.1:3000 your-production-domain.com (it would be impossible to achieve this via the hosts file). Also, instead of IP you can use any domain name (e.g., localhost).
This way, it is possible (but not necessary) to register your Twitter app only once (provided that you don't mind using the same keys for local development and production).
edit this function on TwitterAPIExchange.php at line #180
public function performRequest($return = true)
{
if (!is_bool($return))
{
throw new Exception('performRequest parameter must be true or false');
}
$header = array($this->buildAuthorizationHeader($this->oauth), 'Expect:');
$getfield = $this->getGetfield();
$postfields = $this->getPostfields();
$options = array(
CURLOPT_HTTPHEADER => $header,
CURLOPT_HEADER => false,
CURLOPT_URL => $this->url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false
);
if (!is_null($postfields))
{
$options[CURLOPT_POSTFIELDS] = $postfields;
}
else
{
if ($getfield !== '')
{
$options[CURLOPT_URL] .= $getfield;
}
}
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);
if ($return) { return $json; }
}
I had the same challenge and I was not able to give localhost as a valid callback URL. So I created a simple domain to help us developers out:
https://tolocalhost.com
It will redirect any path to your localhost domain and port you need. Hope it can be of use to other developers.
set callbackurl in twitter app : 127.0.0.1:3000
and set WEBrick to bind on 127.0.0.1 instead of 0.0.0.0
command : rails s -b 127.0.0.1
Looks like Twitter now allows localhost alongside whatever you have in the Callback URL settings, so long as there is a value there.
I struggled with this and followed a dozen solutions, in the end all I had to do to work with any ssl apis on local host was:
Go download: cacert.pem file
In php.ini * un-comment and change:
curl.cainfo = "c:/wamp/bin/php/php5.5.12/cacert.pem"
You can find where your php.ini file is on your machine by running php --ini in your CLI
I placed my cacert.pem in the same directory as php.ini for ease.
These are the steps that worked for me to get Facebook working with a local application on my laptop:
goto apps.twitter.com
enter the name, app description and your site URL
Note: for localhost:8000, use 127.0.0.1:8000 since the former will not work
enter the callback URL matching your callback URL defined in TWITTER_REDIRECT_URI your application
Note: eg: http://127.0.0.1/login/twitter/callback (localhost will not work).
Important enter both the "privacy policy" and "terms of use" URLs if you wish to request the user's email address
check the agree to terms checkbox
click [Create Your Twitter Application]
switch to the [Keys and Access Tokens] tab at the top
copy the "Consumer Key (API Key)" and "Consumer Secret (API Secret)" to TWITTER_KEY and TWITTER_SECRET in your application
click the "Permissions" tab and set appropriately to "read only", "read and write" or "read, write and direct message" (use the least intrusive option needed for your application, for just and OAuth login "read only" is sufficient
Under "Additional Permissions" check the "request email addresses from users" checkbox if you wish for the user's email address to be returned to the OAuth login data (in most cases check yes)

Resources