I'm trying to get a workaround so that i don't have to press the Allow button everytime when I make use of the Twitter API.
if (Request["oauth_token"] == null)
{
//Redirect the user to Twitter for authorization.
//Using oauth_callback for local testing.
oAuth.CallBackUrl = "http://localhost";
Response.Redirect(oAuth.AuthorizationLinkGet());
}
In the code example above i just get a OAuth token but Twitter asks me to confirm that i want to allow access. Is there a workaround so that i don't have to Accept?
I'm afraid the allow step is quite out of your hands. It would be potentially malicious to let a web site authorize a token request on behalf of a user.
Related
Just looking into Blazor and my company decided to explore Server Side App (no WASM).
I got the basic project setup and because we want the app to work with out current user db, I modified our User Server (Microservice) to authenticate a user and return a JWT token. In the Login page once we have the token, we authenticate and the cookie is stored.
var auth = await HttpContext.AuthenticateAsync();
auth.Properties.RedirectUri = "/";
var accessToken = new AuthenticationToken()
{
Name = OpenIdConnectParameterNames.AccessToken,
Value = Token
};
AuthenticationToken[] tokens = { accessToken };
auth.Properties.StoreTokens(tokens);
auth.Properties.IsPersistent = true;
await HttpContext.SignInAsync("Cookies", auth.Principal, auth.Properties);
So I want to say at this point everything is working fine.
Now back to the question. I wish to increase security by using Refresh Tokens, and this is where I hit the problem. Every tutorial or guide I google/bing that talks about Refresh tokens goes by the basses that I am using WASM or an API that I call. There are a few articles that say to use Local Storage but then that can bring up a whole new conversation of Local Storage vs Cookies vs Session, and I was hoping to stick with most of the built in stuff.
I understand that Server-Side issues with the HTTP context, hence why the login page is done on a .cshtml page and the fact that the cookies are set as HTTPOnly so JavaScript cannot access them.
So, is there away to do it?
Just to clarify, this is a Server-Side app only, no client apps or API's or anything else and I wish to stick with most of the built in stuff using cookies.
We're developing a mobile application on iOS and Android with our own back-end and API server using ASP.Net Core with Microsoft.AspNetCore.Identity.
We need to allow users to login with Facebook as optional for default phone/email account.
I followed this and this from Microsoft docs. But this method seems to require the user to login with browser. By creating a controller from the server to redirect user to Facebook login dialog using framework provided Challenge() method.
public class AuthController : Controller
{
...
[HttpGet]
[Route("External/Facebook}")]
public async Task<IActionResult> ExternalFacebook(string myparam)
{
// myparam validation
var scheme = await authService.GetExternalProviderSchemeAsync("Facebook");
var redirectUrl = Url.Action(nameof(ExternalFacebookCallback), null, new { myparam }, Request.Scheme);
var properties = signInManager.ConfigureExternalAuthenticationProperties(scheme.Name, redirectUrl);
return Challenge(properties, scheme.Name );
}
}
Then in ExternalFacebookCallback I only need to verify that the user is authenticated with Facebook and then login/create user to my system, providing my own access token.
The problem for this method is, as mentioned, it seems to require user to be logged in with browser, not the Facebook app. And my user base seems to use Facebook app and don't seem to be happy to log in again in the browser.
We currently use a method that I don't feel happy to use. We let the client use Facebook SDK for iOS and Android to get access_token and post the token to server. The server then use the token with Facebook to verify and get user information.
Is there a better way to do this?
Or the current method is already OK?
Thank you.
For serveral days now I am trying to get OAuth authentication with Google and Facebook to work within my ASP.net core web api project.
my current status is:
I have an ASP.net core Web Api project in which the users need to be authenticated
I have an angular 2 web app which should use my web api (with authentication)
I have an android app, which should use my web api (with authentication)
my goal is:
Using Google/Facebook as OAuth providers for login
later: adding own user accounts (probably with IdentityServer4)
no need to redirect to a special login website (like the IdentityServer4 solution). Just hit the facebook/google button in the app, allow access, done!
In my android and angular app I am able to retrieve the access tokens from google/facebook. Now, I want to use the OAuth implicit flow, to authenticate the user on my web api, with the given access tokens (putting the tokens into the header as bearer token)
There is my problem: is there any genric way to do this easily? I do not want to use the facebook/google SDKs for this.
I have tried following:
using IdentityServer4: With this I am able to login with facebook/google on my webapi, but there is need of a redirection to the IdentityServer4 login page. Is there any possible way of just hitting the google/fb-Button in my app and logging in, without redirection to the identityServer login page?
using the google/facebook authentication middleware (https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/): But they are not validating my sent bearer token (tried countless ways to achieve proper validation). Is this even possible to use within the web api?
trying to use Microsoft.AspNetCore.Authentication.JwtBearer-Middleware and putting in the necessary options for google/facebook by myself, but also not validating (aswell countless attempts)
In the last few days, I have tried so much possible solutions, that I am totally stuck and lost track of what I need to do to achieve this. At this point I have read nearly every asp.net web api oauth tutorial/stackoverflow entry but can't figure out how to use this in my case as I want. Most tutorials are just for mvc-Websites or using IdentityServer4 with the redirection to its login page.
Any suggestions or solutions? What am I missing?
If I undertsand correctly, you already have your Facebook user token from Facebook SDK through your app.
Like you I couldn't find how to do it with an ASP.NET Core library / package. So I went back to basics.
I just call a endpoint of my api with the Facebook token, check it against the Facebook graph api and if fine then I register the user (if required) and return my JWT token as if the user logged through a classical username / password path.
[HttpPost]
[AllowAnonymous]
[Route("api/authentication/FacebookLogin")]
public async Task<IActionResult> FacebookLogin([FromBody] FacebookToken facebookToken)
{
//check token
var httpClient = new HttpClient { BaseAddress = new Uri("https://graph.facebook.com/v2.9/") };
var response = await httpClient.GetAsync($"me?access_token={facebookToken.Token}&fields=id,name,email,first_name,last_name,age_range,birthday,gender,locale,picture");
if (!response.IsSuccessStatusCode) return BadRequest();
var result = await response.Content.ReadAsStringAsync();
var facebookAccount = JsonConvert.DeserializeObject<FacebookAccount>(result);
//register if required
var facebookUser = _context.FacebookUsers.SingleOrDefault(x => x.Id == facebookAccount.Id);
if (facebookUser == null)
{
var user = new ApplicationUser {UserName = facebookAccount.Name, Email = facebookAccount.Email};
var result2 = await _userManager.CreateAsync(user);
if (!result2.Succeeded) return BadRequest();
facebookUser = new FacebookUser {Id = facebookAccount.Id, UserId = user.Id};
_context.FacebookUsers.Add(facebookUser);
_context.SaveChanges();
}
//send bearer token
return Ok(GetToken(facebookUser.UserId));
}
You have to copy the custom code available in this article on medium
Creat a function in AccountController.cs
private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer()
And paste the code given in the article
I've got credentials of an account with access to Google Analytics,
I'm looking to utilise the Analytics Core Reporting API http://code.google.com/apis/analytics/docs/gdata/home.html
I've found examples which use username/password calling setUserCredentials, but have seen comments this is less secure/has a low request limit (And doesn't exist in the lastest client).
Plus I've seem examples which use oauth, but require user interaction and grant access to the users google account.
However I'm looking to run a service which doesn't require any user interaction, and connects to a predefined google account (un-related to the user viewing it).
I can then store the results in a database, and end users can query the results from the database.
I've seen information about using AccessType = Offline when you first login, which then returns an access token and a refreshtoken.
http://code.google.com/apis/accounts/docs/OAuth2WebServer.html#offline
In my example though, the end user will never login to the application.
Could I have a seperate admin application which gets a refresh token, and stores the refresh token in the config/lookup table?
Then the main application can use the refresh token pulling from the config/lookup table, and get an access token to be able to query the Google Analytics account.
I'm looking for a C# example which uses AccessType = Offline, and seperates out the fetching of the refresh token and using the refresh token to get an access token to query the google analytics account.
Create your app https://code.google.com/apis/console/
For you App, turn on access to Google Analytics, and create an OAuth 2.0 client ID for your website.
Browse to:
https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=YOUR_APP_ID.apps.googleusercontent.com&access_type=offline&scope=https://www.googleapis.com/auth/analytics.readonly&redirect_uri=HTTP://YOUR_CALL_BACK_URL
Having changed YOUR_APP_ID, YOUR_CALL_BACK_URL to the relevant values.
Important to include access_type=offline.
Press Grant Access, this will redirect to HTTP://YOUR_CALL_BACK_URL?code=THIS_IS_YOUR_CODE. Copy the code in the URL.
With the code, request the Refresh Token using CMD prompt.
curl -d "code=THIS_IS_YOUR_CODE&client_id=YOUR_APP_ID.apps.googleusercontent.com&client_secret=YOUR_APPS_SECRET_CODE&redirect_uri=HTTP://YOUR_CALL_BACK_URL&grant_type=authorization_code" https://accounts.google.com/o/oauth2/token
Having changed THIS_IS_YOUR_CODE, YOUR_APP_ID, YOUR_APPS_SECRET_CODE, YOUR_CALL_BACK_URL to the relevant values.
Record the refresh_token returned.
Download the latest version of the Core Reporting V3.0 .net libraries
http://code.google.com/p/google-api-dotnet-client/wiki/Downloads
There is a bug in the current version of Google.Apis.Analytics.v3.cs, to fix this copy the code in this file to your local solution (And don’t reference Google.Apis.Analytics.v3.bin)
http://code.google.com/p/google-api-dotnet-client/source/browse/Services/Google.Apis.Analytics.v3.cs?repo=samples&name=20111123-1.1.4344-beta
And change the property Dimensions from a List<system.string> to a string.
Or you'll get an error like me and this guy did http://www.evolutiadesign.co.uk/blog/using-the-google-analytics-api-with-c-shar/
You can then use your Refresh Token, to generate you an Access Token without user interaction, and use the Access Token to run a report against Google Analytics.
using System;
using DotNetOpenAuth.OAuth2;
using Google.Apis.Authentication.OAuth2;
using AnalyticsService = Google.Apis.Analytics.v3.AnalyticsService;
class Program
{
public static void Main()
{
var client = new WebServerClient(GoogleAuthenticationServer.Description, "YOUR_APP_ID.apps.googleusercontent.com", "YOUR_APPS_SECRET_CODE");
var auth = new OAuth2Authenticator<WebServerClient>(client, Authenticate);
var asv = new AnalyticsService(auth);
var request = asv.Report.Get("2012-02-20", "2012-01-01", "ga:visitors", "ga:YOUR_GOOGLE_ANALYTICS_ACCOUNT_ID");
request.Dimensions = "ga:pagePath";
request.Sort = "-ga:visitors";
request.MaxResults = 5;
var report = request.Fetch();
Console.ReadLine();
}
private static IAuthorizationState Authenticate(WebServerClient client)
{
IAuthorizationState state = new AuthorizationState(new string[]{}) { RefreshToken = "REFRESH_TOKEN" };
client.RefreshToken(state);
return state;
}
}
Great Answer Ian and it helped me to get going in the correct Direction more than any other answer I could find online. Something must have changed in the AnalyticsService object because the line:
var request = asv.Report.Get("2012-02-20", "2012-01-01", "ga:visitors", "ga:YOUR_GOOGLE_ANALYTICS_ACCOUNT_ID");
did not work for me and I had to use the following:
var request = asv.Data.Ga.Get("ga:YOUR_GOOGLE_ANALYTICS_ACCOUNT_ID", "2012-01-01", "2012-02-20", "ga:visitors");
Hopefully this will help others like your answer helped me. Thanks!
Ian's answer helped me a lot but I kept getting an error running the curl command. Did some research and found that the steps to get the access code and refresh token can be made easier by going to https://code.google.com/oauthplayground/ and checking your oAuth configuration settings. Top right of the page there is a settings button. selected "Use your own OAuth credentials". You can get your access code and request a refresh token all from here.
Hope this helps.
You can manually get a refresh token from the OAuth Playground.
If you are needing a refresh token for a Service Account as I was, make sure you
Click on the settings on the right.
Check Use your own OAuth credentials
Fill in your Client ID and Secret
Close the settings
Click the Refresh button on step 2
Then save the refresh token for use in your app
What i am Trying to do:
Write a Generic Library in C# to handle OAuth Flow to every service ( Just like Twitter,LinkedIn and Foursquare). The hardest part is that, i want to simulate all the user input in code so that no user action is needed to click on buttons like "Ok,I will Allow It",or even writing its username/password.
Doubts That i have so far:
1 - Whats the usage of the authenticity_token in twitters API ?
2 - What are the factors that all services use, so that i can implement a generic usage of OAuth Flow. For example i´ve found the first Step is really easy to make a Generic method to execute. All i have to do is change the URL for the webRequest,and BAM, i have the Request tokens.
3 - How do i Get the Verifier for each service? In LinkedIn Service for instance, i was able to parse a page to fetch this value, but i can't find this verifier for twitter API for example. Even when authorizing in browser my aplication, i see no Verifier in any HTML during the flow, or any JavaScript generating it.
Observations:
1 - I know that there are Lots of OAuth Libraries out there, like this or that ones, but there is no Library that allows me to make what i want to, that is to Authenticate and authorize a user, without prompting for any user input.
2 - I can't,by any means,ask for user input. All the values like username and password for the authentication, will be hardcoded and every user will use the same account for this requests.
3 - I also know, that there are other posts here that i've written, with almost the same doubts, and the reason i am resposting is to try to make it clearer and fresher.
4 - Sorry about any english mistake or missunderstanding of concepts in advance.
Basic Code Sample:
This is, for instance, the method i am using (that is avaible widely abroad the web) for getting request tokens for any service. All i have to do is change the REQUEST_TOKEN value to the specific url to be used for a service,so i can get the Tokens for LinkedIn,Twitter or Foursquare for instance. But i can't manage to apply the same process in the other steps.
public string AuthorizationLinkGet()
{
string ret = null;
string response = oAuthWebRequest(Method.GET, REQUEST_TOKEN, String.Empty);
if (response.Length > 0)
{
//response contains token and token secret. We only need the token.
NameValueCollection qs = HttpUtility.ParseQueryString(response);
if (qs["oauth_callback_confirmed"] != null)
{
if (qs["oauth_callback_confirmed"] != "true")
{
throw new Exception("OAuth callback not confirmed.");
}
}
if (qs["oauth_token"] != null)
{
ret = AUTHORIZE + "?oauth_token=" + qs["oauth_token"];
}
}
return ret;
}
Don't.
OAuth was designed to require a user to press that button once. If you automate it you will have your application key revoked and your program will no longer work.
What you need to do is save locally the authorization token and reuse that. The user clicks"I Allow" once then you re-use the authorization token for future connections. You need to check to make sure it is not expired, and if it is you just re-authorize and they click "I Allow" again.
No website doing OAuth correctly will allow you to bypass the website authorization, some will allow you to pass the username and password via a query and get a token, but if they have a web authorization, you MUST have the user manually do it.
If you are the OAuth provider and consumer you need to do something Dropbox did for their v0 of the API (I can't find any links to their old API, if anyone can find it edit this post) that passed the username and password to a special address that returned a autorization token without using a webpage. Or you need to use a different authentication scheme than OAuth.