YouTube and OAuth 2.0 in .Net - c#

Does anyone know how to properly authenticate an account using OAuth 2.0 and then use that auth token to access the user's YouTube account?
At the end of http://code.google.com/apis/youtube/2.0/developers_guide_protocol_oauth2.html it says
The Google Data client libraries that support the YouTube Data API do not currently support OAuth 2.0. However, a newer set of Google API client libraries, which do not support the YouTube Data API, do provide OAuth 2.0 support.
As such, it is an option to use these newer libraries, which are listed below, for their OAuth 2.0 capabilities and then force the Google Data client library to use the OAuth 2.0 token(s) that you have obtained.
I have my application successfully running through the OAuth 2.0 process and I'm getting an access token which should be able to access youtube, but I don't know how to "force the Google Data client library to use the OAuth 2.0 token(s)".
Any example code would be great.
Liron
PS This is for a desktop application.

Do do this you need to have both an account set up on google data apps (https://code.google.com/apis/console) and with the youtube apis (http://code.google.com/apis/youtube/dashboard).
You then have to authenticate the google data api using their oauth mechanisms. Something like the following - this is gutted from some code we have.
{code}
//Create Client
m_Client = new NativeApplicationClient(GoogleAuthenticationServer.Description, m_ClientID, m_ClientSecret);
//Add Youtube scope to requested scopes
m_Scopes.Add("https://gdata.youtube.com");
//Get Authentication URL
authStateInitial = new AuthorizationState(m_Scopes);
authStateInitial.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
Uri authUri = m_Client.RequestUserAuthorization(authStateInitial);
//Navigate to URL, authenticate get accessToken
string accessToken = ...;
string[] tokens = accessToken.Split(new char[] { '&' });
if(tokens.Length == 2)
{
authStateFinal = new AuthorizationState(m_Scopes);
authStateFinal.AccessToken = tokens[0];
authStateFinal.RefreshToken = tokens[1];
if(m_AuthStateInitial == null)
{
m_Client.RefreshToken(m_AuthStateFinal);
}
OAuth2Authenticator<NativeApplicationClient> authenticator = new OAuth2Authenticator<NativeApplicationClient>(m_Client, GetState); //GetState returns authStateInitial
authenticator.LoadAccessToken();
}
Then you have to authenticate the youtube apis by using both the access token you got from above and the youtube Developer Key.
{code}
GAuthSubRequestFactory m_Authenticator = new GAuthSubRequestFactory(ServiceNames.YouTube, "Product Name");
m_Authenticator.Token = AccessToken;
YouTubeService m_YouTubeService = new YouTubeService(m_Authenticator.ApplicationName, m_DeveloperKey);
m_YouTubeService.RequestFactory = m_Authenticator;
Hope this helps someone.

Related

How to generate authorization URL for OAuth 2.0 consent screen in .Net Core Console Application?

I know that it is possible to generate OAuth2.0 consent screen URL within a .net framework via deprecated Google.GData.Client library in a bare Console Application. The flow looks like following:
// OAuth2Parameters object, which holds all the parameters related to OAuth 2.0.
OAuth2Parameters parameters = new OAuth2Parameters();
// Set OAuth 2.0 Client Id
parameters.ClientId = clientId;
// Set OAuth 2.0 Client Secret
parameters.ClientSecret = clientSecret;
// Set Redirect URI (in this case it will return authorization code in browser)
parameters.RedirectUri = "urn:ietf:wg:oauth:2.0:oob";
// Set Desired Scope.
parameters.Scope = scope;
// desired URL via OAuthUtil's static method
string url = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
This URL I could open in browser, view Google consent screen, click allow and retrieve authorization code, which I then would use to get appropriate access and refresh tokens
like this:
parameters.AccessCode = Console.ReadLine();
OAuthUtil.GetAccessToken(parameters);
accessToken = parameters.AccessToken;
refreshToken = parameters.RefreshToken;
My major problem is that I would like to do this in a bare .Net Core Console Application (without GData ofcourse), but I struggle to find how. I guess, it is possible to do this in general, at least there are active examples for PHP, Ruby and Python for doing something very similar for
calling YouTube API. Can somebody possibly know, how to do this in .Net Core?
Also, this can't be handled with service account (I don't have problem with that in my app) as users might not be from my organization, so looks like viewing consent screen is necessary.
Oauth2 flow.
Oauth2 is actually easy enough to handle you just need to be able to do HTTP GET and HTTP Post calls.
The first thing we do is create the link that will cause the consent screen to appear. This is a HTTP Get call so can be placed in any web browser.
https://accounts.google.com/o/oauth2/v2/auth?client_id=XXXX.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/userinfo.profile&response_type=code
When the user consents to access the authorization code will be displayed to them on the page.
The next thing you will need to do is exchange that authorization code for an access token and a refresh token.
This is a HTTP POST call, you can do it with .net core easy enouhg here is an example of the call using Curl
curl -s \
--request POST \
--data "code=4/1AY0e-g7BhBt0QU9f5HTgNDGNR1GYtH12q4xvgL_D2Q34A&client_id=XXXX.apps.googleusercontent.com&client_secret=zYAoXDam3mqsdwabh3dQ3NTh&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code" \
https://accounts.google.com/o/oauth2/token
At which point the server will return to you an access token
{
"access_token": "ya29.a0AfH6SMDypscIeiyNnPRvoizz3NvvA6SZdk9U4K8h4MyQRRm29kEc2shdrskPZp71Q1roy8RqIm_7spufW84ozUoSTk0QKkQ",
"expires_in": 3599,
"refresh_token": "1//09Y5LQ0XRxjt-CgYIARAAGAkSNwF-L9IrYzyMnbGtJHgh-FTf6z79cBhQ1hsPUAk71HFgFwqyXoiwpIa-4eA",
"scope": "https://www.googleapis.com/auth/userinfo.profile",
"token_type": "Bearer"
}
If you would like to know how it all works I have a video here Understanding Oauth2 with curl companion blog post How to get a Google access token with CURL
google .net client library
I strongly sujest that you use the Google .net clinet library supports .net core.
The following is an example of authorization with an installed application (console application).
/// <summary>
/// ** Installed Application only **
/// This method requests Authentcation from a user using Oauth2.
/// Credentials are stored in System.Environment.SpecialFolder.Personal
/// Documentation https://developers.google.com/accounts/docs/OAuth2
/// </summary>
/// <param name="clientSecretJson">Path to the client secret json file from Google Developers console.</param>
/// <param name="userName">Identifying string for the user who is being authentcated.</param>
/// <param name="scopes">Array of Google scopes</param>
/// <returns>authencated UserCredential</returns>
private static UserCredential GetUserCredential(string clientSecretJson, string userName, string[] scopes)
{
try
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(clientSecretJson))
throw new ArgumentNullException("clientSecretJson");
if (!File.Exists(clientSecretJson))
throw new Exception("clientSecretJson file does not exist.");
// These are the scopes of permissions you need. It is best to request only what you need and not all of them
using (var stream = new FileStream(clientSecretJson, FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/", System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
// Requesting Authentication or loading previously stored authentication for userName
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
scopes,
userName,
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
credential.GetAccessTokenForRequestAsync();
return credential;
}
}
catch (Exception ex)
{
throw new Exception("Get user credentials failed.", ex);
}
}
Both my website Daimto.com and my YouTube channel Daimto developer tips Have examples for using the google apis with .net. I also have a github project Google-Dotnet-Samples with examples for most of the apis.

Dynamics CRM api HttpClient Request Authentication with ADFS 3.0

I have an on-premise Dynamics CRM (2016) that is configured with ADFS (3.0). When a user want's to Login, they get redirected to the ADFS login page and the user enter their Windows AD credentials.
From a .net core application I need to make request to the CRM api using HttpClient. When I try to send the credentials like I normally would for a Windows Auth CRM it doesnt work. I get a 401 Unauthorized. Like below.
HttpClient client = new HttpClient(new HttpClientHandler() { Credentials = new NetworkCredential("myuser", "mypassword", "mydomain") });
var result = client.GetAsync("https://mycrmaddress/api/data/v8.0/accounts");
I also tried using Adal to retrieve a token and attach it as a bearer token to the request but I'm unable to get a token with adal. When I try I receive the following:
The authorization server does not support the requested 'grant_type'. The authorization server only supports 'authorization_code'
ADFS 3.0 doesn't support this flow.
I cannot upgrade to ADFS 4.0 so I would like to know what are my options to make an authenticated call to CRM api (without prompting a login window as this application is a service).
Is there any configuration I can do on ADFS so my first example work? Or is it possible to do it with Adal even if it's ADFS 3.0? Or any other solution...
I found the answer to my question. It's kinda hackish, but I tested it myself and it works. As a temporary solution this will do the trick.
Details are available here: https://community.dynamics.com/crm/f/117/t/255985
ADFS 3.0 supports the Authorization Code flow and this what we will use in this case.
We need to retrieve an authorization code. Normally at this steps a windows is prompted to the user to enter its credentials. By doing a POST and sending the user/password it's possible to retrieve an authorization code.
{authProvider} - ADFS Uri - something like
https://adfs.mycompany.com/adfs/oauth2/
{ClientId} - The Guid used to
by your infrastructure team to add your application to ADFS
{RedirectUri} - The IFD Uri for dynamics - should match the redirect
Url used to by your infrastructure team to add your application to
ADFS
username - The User set up on ADFS and in Dynamics
password - The password for the above user
Then we make the following call with these information using HttpClient.
var uri = $"{authProvider}authorize?response_type=code&client_id={clientId}&resource={redirectUri}&redirect_uri={redirectUri}";
var content = new FormUrlEncodedContent(new[] {
new KeyValuePair<string,string>("username",username),
new KeyValuePair<string,string>("password",password),
});
var responseResult = _httpManager.PostAsync(uri, content).Result;
The response content will be an html page (Remember normally this flow prompts a login page to the user). In this page there will be a form that contains the authorization code. using a library like HtmlAgilityPack retrieve the token. This is the hackish part of the solution.
Now that we have an authorization code we need to retrieve an access token.
For that we need to make the following call
var uri = $"{authProvider}token";
var content = new FormUrlEncodedContent(new[] {
new KeyValuePair<string,string>("grant_type","authorization_code"),
new KeyValuePair<string,string>("client_id",clientId),
new KeyValuePair<string,string>("redirect_uri",redirectUri),
new KeyValuePair<string,string>("code",code)
});
var response = await _httpManager.PostAsync(uri, content);
The response content will be a json string that will contain the access token.
With the access token, make the call to CRM rest API.
You will need to attach the token to the HttpClient in the header as a bearer token.
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",token);
httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");
From now on you can make calls to CRM api and you will be authorized. However be carefull normally access token are short lived. You will either need to increase their lifetime or request a new token everytime it's expired.

How to implement OAuth 2.0 in ASMX (web-reference)?

I am very new in implementing OAuth 2.0. I have implemented web-reference (ASMX file) in my xamarin project. Now I need to implement OAuth 2.0 for authentication. But I am not sure if ASMX supports OAuth2.0 or not. Do I need to implement WCF instead of Web refernce(ASMX) or is it possible in web reference (ASMX) to implement the OAuth2.0?
One possible solution is to add the token aquired from the authority to the Authorization header.
Your code could look similar to this:
var redirectURI = Windows.Security.Authentication.Web.WebAuthenticationBroker.GetCurrentApplicationCallbackUri();
var _authContext = new AuthenticationContext(authority);
var tokenResult = await _authContext.AcquireTokenAsync(serviceResourceId, clientId, redirectURI);
if (tokenResult.Status != AuthenticationStatus.Success)
{
//Not authenticated
return;
}
var svc = new YourServiceReference.YourClient();
using (var scope = new OperationContextScope(svc.InnerChannel))
{
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = tokenResult.AccessToken;
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
var result = svc.MyFunction();
//Do something with the data
}
Tricky - this is how mobile OAuth solutions work - but it is a big job:
Your Xamarin app would need to implement Mobile SSO to sign users in
Users of your Xamarin app would be redirected to login via an Authorization Server / Identity Provider after which they will receive an OAuth access token
After login your Xamarin App would then be able to call an API with the token and act on behalf of the user to get data
The API would need to validate received access tokens
SOLUTION PARTS
API: ASMX is an old technology so if you are working on the Microsoft stack you would use something newer such as a .Net Core Web API
MOBILE APP: The harder part of the solution will be implementing Mobile SSO, if you have not done so already.
How much of this solution exists already?

Can I use Chrome Web Store payments with OAuth 2.0

I've written a hosted Chrome Web App which authenticates the user with OAuth 2.0 using the Google APIs Client Library for .NET. Now I want to add payments to our application using the in-built Chrome Web Store Payments.
Looking at the documentation it appears that I need an OpenID URL in order to check for payment.
How can I get this UserID/OpenID URL since I'm using OAuth instead of OpenID authentication?
var service = new Google.Apis.Oauth2.v2.Oauth2Service(
new BaseClientService.Initializer
{
HttpClientInitializer = userCredential,
ApplicationName = "My App Name",
}
);
HttpResponseMessage message = await service.HttpClient.GetAsync(
string.Format("https://www.googleapis.com/chromewebstore/v1/licenses/{0}/{1}",
appId,
fedId // Where do I get this??
)
);
I wanted to leave my own experience here so that others can see that it's not just a matter of using the existing Id returned from an authorised request to the user profile endpoint, as this is not the ID required by the Chrome Payments API...
Short Answer
It's not possible to use only OAuth2.0 for a hosted app. The only options for a hosted app are:
Use the deprecated OpenID (see detailed answer)
Use In-app Payments using Google Wallet for Digital Goods
Long Answer
We still have to use OpenID, however Google has provided a migration path for OpenID users to OAuth2.0 called OpenID Connect. The aim of this migration is to map the old fedId field to new the Google+ User Ids.
This allows us to retrieve an OpenID identifier using an existing OAuth 2.0 process.
Caveat: The Google .NET Client APIs do not support this migration path. So authentication must be done manually or using a 3rd party OAuth library.
Howto:
As per usual OAuth flow, direct the user to the Authenticate endpoint (https://accounts.google.com/o/oauth2/auth) with the following variables:
openid.realm=http://localhost ** Required, where http://localhost matches your redirect_uri variable
scope=openid profile https://www.googleapis.com/auth/chromewebstore.readonly ** Both openid and profile scopes are required in order to retrieve the OpenID identifier. The chromewebstore scope is required to query the payments API.
Then exchange the code for an access token from the Token endpoint (https://accounts.google.com/o/oauth2/token)
At this point you will receive the standard access_token, refresh_token, etc variables but also an additional id_token variable.
This id_token is a JWT-encoded string containing the OpenID information.
Decoding this JWT-encoded (you can use this C# JWT Library) string will give you a JSON string in the following format:
{
"aud": "<googleuserid>.apps.googleusercontent.com",
"at_hash": "<hashcode>",
"iss": "accounts.google.com",
"openid_id": "<!! The fedId we require !!>",
"exp": <id>,
"azp": "<googleuserid>.apps.googleusercontent.com",
"iat": <id>,
"sub": "<googleuserid>"
}
At this stage we've finally found what we're looking for, the openid_id. This can be used to communicate with the Chrome Payments API
While still using the same OAuth credentials, make a signed request to the following URL:
https://www.googleapis.com/chromewebstore/v1/licenses/{appId}/{openId}
{appId} is the ID of your app within the Chrome Web Store
{openId} is the openid_id from the JWT response
This should give you what you need:
https://developers.google.com/accounts/docs/OAuth2
Its a complete overview of OAuth2.0.
Helped me with a problem I was having with a webapp setup, hope it can do the same.
P.S - Im not sure but this may be exactly what your looking for:
https://developers.google.com/accounts/docs/OAuth2InstalledApp

How to use OAuth 2 - OAuth 2 C# example

I have to figure out how to use OAuth 2 in order to use Deviantart api.
I got the client_id and client_secret part
Here the information they give
Endpoints
The only information you need to authenticate with us using OAuth 2.0 are the client_id and client_secret values for your app, as well as the endpoint shown below.
OAuth 2.0 draft 10:
https://www.deviantart.com/oauth2/draft10/authorize
https://www.deviantart.com/oauth2/draft10/token
OAuth 2.0 draft 15:
https://www.deviantart.com/oauth2/draft15/authorize
https://www.deviantart.com/oauth2/draft15/token
Placebo call
The first API call relying on OAuth 2.0 authentication is the placebo call.
It's useful for checking that an access token is still valid before making a real API call that might be long, like a file upload.
You call it with one of the following endpoints (an access token must be provided):
https://www.deviantart.com/api/draft10/placebo
https://www.deviantart.com/api/draft15/placebo
You need to use the endpoint that corresponds to the OAuth 2.0 draft you've obtained your token with.
It always returns the following JSON: {status: "success"}
I have searched the web and found this awesome library.
DotNetOpenAuth v4.0.1
http://www.dotnetopenauth.net/
Added it as reference but have no idea what to do next. Even a very small example would be really useful about how to use OAuth 2
using DotNetOpenAuth;
using DotNetOpenAuth.OAuth2;
Here the page where deviantart gives the information
http://www.deviantart.com/developers/oauth2
Ok here what i got so far but not working
public static WebServerClient CreateClient() {
var desc = GetAuthServerDescription();
var client = new WebServerClient(desc, clientIdentifier: "myid");
client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter("mysecret");
return client;
}
public static AuthorizationServerDescription GetAuthServerDescription() {
var authServerDescription = new AuthorizationServerDescription();
authServerDescription.AuthorizationEndpoint = new Uri(#"https://www.deviantart.com/oauth2/draft15/authorize");
authServerDescription.TokenEndpoint = new Uri(#"https://www.deviantart.com/oauth2/draft15/token");
authServerDescription.ProtocolVersion = ProtocolVersion.V20;
return authServerDescription;
}
Easiest thing to do now is get Visual Studio 2013 and create a new ASP.NET Web Application choosing "Individual User Accounts" as your authentication type. There's a working OAuth 2 implementation out of the box in there (configured at App_Start\Startup.Auth.cs) which you can slice out and then adapt to your needs.
In the ASP.NET Core Security Project there is now a ready to use solution:
Nuget Package: AspNet.Security.OAuth.DeviantArt

Categories

Resources