Windows Phone app using OAuth2 - c#

I'm starting to develop an application for fun that uses OAuth2. I'm using this API from Trakt http://docs.trakt.apiary.io/#reference/authentication-oauth/authorize/authorize-application
Right now, what I want to do is the authentication, but having some problems with the code.
I have no nuget packages helping, and here's the code I have.
System.Uri myUri = new System.Uri("https://api-v2launch.trakt.tv/oauth/authorize?response_type=code&client_id=" + CLIENT_ID + "&redirect_uri=urn:ietf:wg:oauth:2.0:oob");
webBrowser.Visibility = System.Windows.Visibility.Visible;
webBrowser.Navigate(myUri);
CLIENT_ID is given by the website API, and it says to put "urn:ietf:wg:oauth:2.0:oob" for local tests.
When I run the application, I get a page to login, then I get the "Authorize" and "NO" question. If I click the authorize, It gives me a code, which i'll need to use after.
Though, I'm having an hard time to do a GET method to get that code, or to get the error if the person clicks "NO"
Can you guys help me? With a single GET method, I should be able to do the POST method and continue to develop the application.
Thanks for help

There are two things you need to do.
1) You need to set the URI to: ms-app://{package-security-identifier}
The package identifier is your unique app id.
2) In Trakt you need to add this redirect URI (you do this in your application settings).
Check this Facebook Developer post for details about using their login flow, it is similar: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2

Related

Is there a way to get current Google Authenticator 2FA key for a specific account (client-side)

I am searching for a way to obtain the current code in my Google Authenticator app. for a specific account.
Please note that I'm not looking for embedding Google 2FA to any of server-side application - I guess it has been already well-documented.
I am trying to get the same current code shown in my own Google 2FA app. (by providing my Google credientials ofcourse) so I can make my app fully automated even when logging in (to a specific system/website) without asking for the code each time I start the app.
Thanks by now.
UPDATE:
Even if I can't find any answer or simply "there is no way", there is still a way even if it's too ugly.
Running an ios/android simulator (and configure it once by installing the Google Auth app) and simulate the mouse clicks over it and then capturing a screenshot and decoding the code from the image would be much of a work but also can actually work. I'm just trying to find a better way, if there is any.
You could solve this by generating the OTP code locally using a library such as OTP.Net. Simply save the secret locally, and add it to .gitignore if using git.
Then you can make a code on demand like so:
using OtpNet;
var totp = new Totp(secretKey);
var totpCode = totp.ComputeTotp();

Google Contacts API version 3.0 (.NET) - OAuth2.0 CRUD Operations

I have setup up a .NET console application that will do the following:
Access the Google Contacts API for my personal Google Account
Perform basic CRUD (create, read, update, delete) operations to these contacts
I believe executing the CRUD operations will be straight forward using the following documentation:
https://developers.google.com/google-apps/contacts/v3/#about_authorization_protocols
However, my problems are occurring when trying to authenticate my connection using OAuth2.0.
I am using the Google.GData.Contacts .NET NUGET Package using the code from the following example:
https://code.google.com/p/google-gdata/source/browse/trunk/clients/cs/samples/oauth2_sample/oauth2demo.cs?r=1159
OAuth2Parameters parameters = new OAuth2Parameters() {
ClientId = clientId,
ClientSecret = clientSecret,
RedirectUri = redirectUri,
Scope = scopes
};
string url = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
Console.WriteLine("Authorize URI: " + url);
parameters.AccessCode = Console.ReadLine();
OAuthUtil.GetAccessToken(parameters);
As this code was last updated in 2012, I'm worried it might no longer be relevant for my task.
Major Questions:
I'm not sure exactly what the parameters.AccessCode value is. Where does this value come from?
Based upon my use case am I using the correct OAuth2.0 approach? You can can setup authentication for a Service Account, Web Application, or Native Application. The above code implies Native Application
Is there a better way to handle my task?
The access code should be used only for WebServer Applications.
I'm not sure if your console app will run in an environment where a browser can be launched or not.
If yes (your app is running in a environment where a URL can be launched), use the documentation for Installed Applications.
If browser is not present, you can use the documentation for Applications on limited-input devices.
If the library you're targeting to use (NUGET, whatever) has no support for this flow, don't worry: it's easy to write custom code. You can use any library able to do HTTP/HTTPS requests, like or Windows.Web.Http.HttpClient (Windows 8 and later).
Additionally, you can use contact import services like CloudSponge, which offers a .Net API and support for other contact sources (in case you want expand your address book support in the future).
AccessCode comes from the URL created in that Line above. See here:
string url = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
url contains a URL now for your browser. Fill it in Chrome/Firefox/etc and confirm the google request to get the AccessCode. It will look like this "4/bAQT1qf66vpkmfU8xDkoVZmedvVoYDH6KovzcHcA5pc" but will change every time you call the URL.
Console.WriteLine("Authorize URI: " + url);
now you can see the url but you might not be able to copy it from your console. But if you get it into your browser, it will result in a google dialog to get your AccessCode.

Is there a naming standard for REDIRECT URIS OAuth 2.0?

I just want to know if there is a naming standard on REDIRECT URIS for :
Twitter, LinkedIn, Microsoft, Facebook and Google when using OAuth 2.0?
Because, if I write my domain like that : http://domain.com/account/external-signin.aspx every external login stop working except Twitter and Facebook. The name account/external-signin.aspx is the real URL I'm working with and that I'm supposed to give to every external login.
So, Microsoft give this error:
We're unable to complete your request
Microsoft account is experiencing technical problems. Please try again later.
LinkedIn:
Invalid redirect_uri. This value must match a URL registered with the API Key.
And Google
400. That’s an error. Error: redirect_uri_mismatch
If I remove the page extension .aspx it seems to work although I deliberately write a wrong url like http://domain.com/sign-google, http://domain.com/sign-microsoft etc...
I'm working with MVC5 and C#.
I think I missed a few things ...
Thanks for your help
So finally, here is the correct answer:
It's not you that choose the redirect URL. You must write your domain.com/signin-{suppliername} in your app management.
Example:
Microsoft : https://domain.com/signin-microsoft
LinkedIn : https://domain.com/signin-linkedin
Google : https://domain.com/signin-google
Facebook and Twitter can work with your own redirect URL. Once successfully registered, the effect is immediate. Hope this can help somebody.
Karine
This error is denoting that you're having a miss match with the URL you're returning, and the return URL registered at the API Server. When you register your application, at the server, (for Google: https://code.google.com/apis/console) you have to make sure that the URLs being used would be matching.
After this, you will not get this error, I think on the server you've set this property to, http://domain.com/account/external-signin (without aspx; as you've said that this works without the extension but not with it). So try to change it on the server too.
For Linkedin append your url with "signin-linkedin".e.g. if your url is http://localhost:{portnumber}, make sure its is register in linked in as "http://localhost:{portnumber}/signin-linkedin" and this will do the trick.
Happy Codding :)

OWIN's GetExternalLoginInfoAsync Always Returns null

I've created a new MVC5 Web Application, and when I try to login with Google or Facebook, the ExternalLoginCallback Action in the AccountController is called, but GetExternalLoginInfoAsync() always returns null:
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
Because it's always null, it just redirects back to the login page and the process starts over. How can I fix this?
To get OWIN Google login to work properly on a standard Visual Studio 2013, ASP.Net MVC5 site, I had to:
Setup a Google OpenId account at https://console.developers.google.com/project
Set the callback URL there to blah/signin-google. Important notes on things you don't need to do:
You don't need to use HTTPS for Google to redirect back; you can even redirect back to plain http://localhost, no problem.
You don't need to setup anything for the redirect URL - no routes, Controller Actions or special permissions in Web.Config. The redirect URL is always /signin-google and OWIN handles this behind the scenes for you.
As an example, if your site was me.com, you might have these 3 callback URLs in the Google Developer Console:
http://localhost:53859/signin-google
http://test.me.com/signin-google
https://me.com/signin-google
The first one including whatever port number VS gave you for your project.
Enable the Google+ API. This is one hidden b**** of a gotcha and is the root cause of the problem in the question here - if you don't do this, it's easy to miss that the Request to /account/ExternalLoginCallback includes &error=access_denied, and that's because Google said no to a permissions request OWIN made for the user's Google+ basic profile. I can't tell whose fault this is, Google's or Microsoft's.
To enable the Google+ API in the Developers Console, click APIs on the left, hunt for Google+, click that and hit Enable. Yes you really do need to do that. You're hosed if you don't do that.
Add the ClientId and ClientSecret Google gave you in the Developers Console to Startup.Auth, but improve the code in the process to explicitly use OAuth2, and explicitly ask for the user's email address:
var google = new GoogleOAuth2AuthenticationOptions()
{
ClientId = "123abc.apps.googleusercontent.com",
ClientSecret = "456xyz",
Provider = new GoogleOAuth2AuthenticationProvider()
};
google.Scope.Add("email");
app.UseGoogleAuthentication(google);
That's it. That finally got it working.
Just want to reiterate one more time, there are a LOT of answers about this and issues like it where OWIN/Google isn't working, and nearly all of them are wrong for the current VS2013/MVC5/OWIN template.
You don't need to modify Web.Config at all.
You don't need to create any special Routes whatsoever.
You should not attempt to point /signin-google to a different place, or use a different callback URL, and you definitely shouldn't attempt to tie it directly to /account/externallogincallback or externalloginconfirmation, because those are both separate from /signin-google and necessary steps in the OWIN/Google process.
OK, I found out why it's null. You have to enable Google + API in the Google console. Also make sure the secret key is not concatenated with a space at the end after you paste it to your code. Why can't they return a normal error? I don't know.
It seems that Nuget package Microsoft.Owin.Security.Facebook version 3.0.1 no longer works with Facebook Login.
Update this package to the pre-release 3.1.0 version, you can use the following:
Install-Package Microsoft.Owin.Security.Facebook -Pre
As others correctly mentioned, most of the time that's because you do not have permission to the Google+ API so here is how to get permission for a project in Google API Manager to Google+ API
Step 1. Select You Project from the top combobox and go to Dashboard > Enable API
Step 2: Search for Google plus and select it
Step 3: Enable it!
if you return to dashboard for that project you can see the list of enabled API's for that project at the bottom
I got it to work by simply updating all the nugget package in the application and it worked.
I know it's silly, but after a long struggle, restarting IIS solved the issue for me.
This solved my problem:
Enable the Google+ API. This is a gotcha and is the root cause of the problem in the question here - if you don't do this, it's easy to miss that the Request to /account/ExternalLoginCallback includes &error=access_denied, and that's because Google said no to a permissions request OWIN made for the user's Google+ basic profile. I can't tell whose fault this is, Google's or Microsoft's.
To enable the Google+ API in the Developers Console, click APIs on the left, hunt for Google+, click that and hit Enable.
I did the following to get it working.
Logon to the developer portal, locate your application and do the following.
App details > App centered Listed Platforms > Select Yes for website
I ran in to this issue today and it turned out that I defined the remote cookie after I assigned the providers.
Make sure you place...
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
before...
app.UseFacebookAuthentication(
appId: "",
appSecret: "");
I wanted to contribute to this one also. I just recently got this working. I had the problem with the GetExternalLoginInfoAsync returning null but only in production.
After a lot of searching I finally found my answer it was simply a problem with my database. In production I had set the wrong connection string so it would not connect properly but it was basically silent about it. The only thing that happened was GetExternallLoginInfoAsync returned null. So check you database connection string if this happens!
Also on a sidenote, the only thing that was needed to get this working was:
Set up a project in the Google console
Enable Google+ API
Copy your client id and client secret to the Startup.Auth.cs file.
You do not have to enable HTTPS, you do not have to create custom routes. But make sure your database is working properly!
For those who are experiencing this problem for Web Api. Other solutions doesnt help AuthenticationManager.GetExternalLoginInfoAsync(); returns always null even google plus api is enabled.
use this custom function to get logininfo. obviously Microsoft has a bug for GetExternalLoginInfoAsync when requesting over web api.
private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer()
{
ExternalLoginInfo loginInfo = null;
var result = await Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalBearer);
if (result != null && result.Identity != null)
{
var idClaim = result.Identity.FindFirst(ClaimTypes.NameIdentifier);
if (idClaim != null)
{
loginInfo = new ExternalLoginInfo()
{
DefaultUserName = result.Identity.Name == null ? "" : result.Identity.Name.Replace(" ", ""),
Login = new UserLoginInfo(idClaim.Issuer, idClaim.Value)
};
}
}
return loginInfo;
}
Although the answers above are all good, in my instance none of these worked - I'd checked and double checked the Google settings and agree with Chris Moschini that there's a lot of misleading info.
For me it was a 'doh moment when I realised that my Out of Process state service was not started! No errors (as a login was the first thing I was attempting after a reboot where the state service is set to manual start-up on the machine) just a Null from GetExternalLoginInfoAsync
Hope this helps someone else out.
After much searching and head scratching as well as following numerous red herring answers here on Stackoverflow I eventually went through all my options on my Google dev console and discovered a little blue [Enable] button on the Google+API overview page. I clicked this and hey presto it worked. Forget all the baloney you read about callback url and route configs, OWIN overrides the google default /signin-google redirect uri in any case and sends you back to ExternalLoginCallback. Just stick with the default implementation all will be good so long as you enable your Google+API.
It is true that you are going to need the Google plus Enabled. The big thing for me was the project URL. Open the properties window (View -> Properties Window) in VS and then right click the project and select properties. In small properties window copy your SSL URL, and then in the larger properties window select the Web tab and paste that URL in the Project URL.
Fixed the issue for me.
See in greater detail: https://learn.microsoft.com/en-us/aspnet/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on
For me I was migrating and old but working .NET 4.6.1 MVC website to core 1.1. Work stopped before I could get it working, when I picked it back up, I was then migrating to 2.x.
My problem was that the callback from Google was met with a 404 from my site. I thought it was supposed to hit AccountController.ExternalLoginCallback so I added a [Route(...)] to it and sure enough, Google's callback hit the action.
This then hit the null returned in this line (what kind of maniac returns a null?)
var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
I reverse engineered it to find under the hood its ultimately getting the handler for ExternalScheme which for my was the cookies handler!
It all seemed wrong and I felt somehow that the middleware was supposed to just intercept the callback URI so I removed my [Route(...)] and the 404 problem came back.
I then found that I need to add this during startup.
applicationBuilder.UseAuthentication();
This solves the 404 but gives another issue.
No authenticationScheme was specified, and there was no DefaultSignInScheme found.
By adding a default scheme here, I resolve the error above.
serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme)
.AddGoogle(googleOptions => Configuration.Bind("OAuth2:Providers:Google", googleOptions))
.AddExternalCookie();
Now AccountController.ExternalLoginCallback is invoked again by some magic but I am back to the null return value.
I added this code above the offending line, which is essentially what is happening under the hood (looking at Microsoft's code on GitHub). Interestingly, h is of type CookieAuthenticationHandler and a has all my claims and information from Google inside!
var authHandler = this.HttpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
var h = await authHandler.GetHandlerAsync(this.HttpContext, IdentityConstants.ExternalScheme);
var a = await h.AuthenticateAsync();
var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
Digging into GitHub and copy pasting internal code its running into my controller, I can see that it's failing to find ClaimTypes.NameIdentifier in my claims, this is the ProviderKey used later.
Hmm....
Concerned I was using old 1.x AccountController code with newer 2.x identity bits I did find some samples that still use this stuff, and some samples that use Razor Pages for it all, too. I'll continue with what I have.
So I'm next going to investigate mapping additional Google user JSON payload items into the claims. I think if my Google account ID (numeric, I guess) was mapped then everything would work.
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/additional-claims?view=aspnetcore-2.2
Final Fix
I finally resolved the issue by adding a "claim action" to pull my Google identifier out of the JSON coming back from Google!
serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme)
.AddGoogle(googleOptions =>
{
Configuration.Bind("OAuth2:Providers:Google", googleOptions);
googleOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
})
.AddExternalCookie();
The sub field contains what eventually ends up in the nameidentifier claim and then into the ProviderKey that the AccountController wants.
In my case the solution was update Nuget package Microsoft.Owin.Security and Microsoft.Owin.Security.Google
All of the other answers didn't solve this for me, so if your in the same boat then make sure your registration controller action has the RequireHttps attribute:
// GET: /Account/LoginRegister
[AllowAnonymous]
[RequireHttps]
public ActionResult LoginRegister()
{
return View(new RegisterLoginViewModel());
}

Is there a way to customize the Thinktecture.IdentityServer.v2 login page?

I'm using the Thinktecture.IdentityServer.v2 app to perform SSO for a couple of internal apps but would like to customize the login page for each application to have a smoother user experience. I can't seem to find a way to do that.
Can the login page be customized depending on the source application from where the client is comming?
"I can't seem to find a way to do that." - How hard have you tried? ;)
The RP has the extra data fields - so you can hang like a CSS name off the RP in the registration database. Further you can get to that RP data from the signin page - quoting the comment in AccountController:
// you can call AuthenticationHelper.GetRelyingPartyDetailsFromReturnUrl to get more information about the requested relying party
btw - IdentityServer's github repo has an issue tracker - you should use that for questions.
You can always have the RP pass a custom query string param and customize off of that. But you're outside the bounds of WS-Federation at that point. Plus, you must think about the nature of SSO -- the user is really signing into the IdP, not the app. So changing the IdP to look like the app is somewhat disingenuous.
I have solved this by customizing the SignIn.cshtml to adjust the style to what I need. Additionally, I have server side code in the top of SignIn.cshtml that does some string matching on the ReturnUrl (Request.QueryString["ReturnUrl"]). Then I show a different logo and header text based on some values I know to be unique for the different RP urls.
When upgrading to a new version of the ThinkTecture MVC, it will be a small job to update only this file to your specifics (just remember to have a copy of your modified SignIn.cshtml before you upgrade).

Categories

Resources