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
Related
Edit:
Here is my question reformulated:
I have a web server with secured api endpoints - one must have been authenticated with Google prior to using them. I implemented Challenge and Callback endpoints for that.
This works well from a browser with my SPA web front-end. The user gets redirected to the Google website to sign-in and then gets redirected back to my webapp; the browser then has the authenticated cookies and the webapp can use the endpoints to update its state.
I also have a WPF application that will communicate with the web server.
I want the WPF application to do the same as the web front-end: Use the web api endpoints after being authenticated with Google. The connection between the WPF application and my web server is done through an HttpClient.
My problem is I don't know how to authenticate that HttpClient connection between the WPF app and the web server.
I tried using the same Challenge endpoint but the response I get is of course the HTML from the Google Sign-In page, so I guess I can't use that with an HttpClient...
I also tried authenticating with GoogleApis from the WPF app and use the authenticated token to set cookies in the HttpClient but apparently this is not compatible.
How to authenticate an HttpClient connection to a web api with an external provider such as Google?
Original question:
From a WPF application, the user authenticates with Google with this code:
using Google.Apis.Auth.OAuth2;
...
public void Authenticate()
{
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "myClientId",
ClientSecret = "myClientSecret"
},
new[] { "email", "openid" },
"user",
CancellationToken.None).Result;
}
This works and the UserCredential object contains the authenticated token:
How to embed this token information in a web request made with an HttpClient in order to call my webapi endpoint?
I think the request must include some cookies to inform the server that it has been authenticated, but I don't know which ones exactly.
The endpoint on the server-side validates that the user is authenticated with the help of IdentityServer:
var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
If I got your question right, you just have to set the Authorization header
var credentials = await GoogleWebAuthorizationBroker.AuthorizeAsync(
clientSecrets,
new[] { "email", "openid" },
"user",
CancellationToken.None);
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
credentials.Token.TokenType,
credentials.Token.IdToken);
Maybe you'll find below a helpful hint to better understand OpenID :)
The confusion stems from mixing GoogleApis and IdentityServer frameworks.
Authentication/authorization can be achieved using either of them.
Objects from Google.Apis.Auth.OAuth2 and IdentityServer4 namespaces are not designed to interact.
No manual cookie handling is necessary, for sure.
Ask yourself to whom does Google provide trust for the user. If it calls back to WPF, then webapi trusting WPF is a separate issue.
You answer your own question in the question:
the browser then has the authenticated cookies and the webapp can use
the endpoints to update its state
HttpClient needs to send those same cookies.
How do I set a cookie on HttpClient's HttpRequestMessage
If I understood your question right, then I faced the same problem not too long ago.
The way I implemented it is that in the backend, no matter who tries to access the endpoint, they had to send a Bearer X authorization token.
The token contained the identity of the client that wanted to access the resource, and I checked if he was permitted.
No matter what kind of client wants to access the endpoint, it just has to have that authroziation header in the request that he sends and the backend will treat it the same.
In my scenario, I used an authentication service that returns a cookie to the client with a certain JWT that contains the identity information.
Then from the client I send in every request the JWT received from the authentication service as an authorization header to the backend.
The reason I had to put the JWT that I receive from the service in a header, is that the authentication service and the backend service are not in the same domain, so cookies cant be shared.
This results in such design that no matter how you authenticate the client, the end result must be some sort of token that the backend can receive and read.
Hope this helps.
Scenario
I have an Exchange Online environment and service/daemin (no interactive user) application on the Azure VM. Service uses EWS managed API to work with emails in the mailbox of any tenant user. Now EWS client uses Basic authentication that, according to Microsoft, will become unsupported in EWS to access Exchange Online.
Question/Issue
So, I need to find a way to get valid access token for service/daemon application to use with EWS managed API.
My findings
The following article shows an example of using OAuth 2.0 with EWS managed API. This example works, but it uses interactive method of getting consent (sign-in form appears allowing user authenticate themselves and grant requested permission to application) that is not suitable for service/daemon app scenario, because there is no interactive user.
For service/daemon application I need to use client credential authentication flow.
Registered application
Using admin account on https://aad.portal.azure.com portal I registered application with Azure Active Directory. Added client secret for registered application.
Aforementioned article uses https://outlook.office.com/EWS.AccessAsUser.All as a scope. But I did not find permission with such a URL on the portal. I found only the following permissions under Office 365 Exchange Online > Application permissions > Mail:
https://outlook.office365.com/Mail.Read Allows the app to read mail in all mailboxes without a signed-in user
https://outlook.office365.com/Mail.ReadWrite Allows the app to create, read, update, and delete mail in all mailboxes without a signed-in user.
I added both of them and granted admin consent for all users.
Getting access token
For testing purposes and simplicity I did not use any auth libraries (ADAL, MSAL etc.). I used Postman to get access token, then set token variable in debug (see code snippet later in the post).
I tried different endpoints to get acess token.
OAuth 2.0 token endpoint (v2)
POST: https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token
grant_type=client_credentials
client_id=***
client_secret=***
scope=https://outlook.office.com/EWS.AccessAsUser.All
Sending this request produces the following error response:
AADSTS70011: The provided request must include a 'scope' input parameter. The provided value for the input parameter 'scope' is not valid. The scope https://outlook.office.com/EWS.AccessAsUser.All is not valid.
I tried changing scope to https://outlook.office.com/.default. Access token was returned, but it appeared to be invalid for EWS. EWS client throws 401 error with the following value of x-ms-diagnostics response header:
2000008;reason="The token contains no permissions, or permissions can not be understood.";error_category="invalid_grant"
OAuth 2.0 token endpoint (v1)
POST: https://login.microsoftonline.com/<TENANT_ID>/oauth2/token
grant_type=client_credentials
client_id=***
client_secret=***
resource=https://outlook.office.com
Access token was returned, but also appeared to be invalid for EWS. EWS client throws 401 error with the same value of x-ms-diagnostics response header as described ealier in #1.
Use aquired access token with EWS managed API
Here is code sample that I used to test EWS client with access token acquired in Postman:
var token = "...";
var client = new ExchangeService
{
Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
Credentials = new OAuthCredentials(token),
ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress,
"user#domain.onmicrosoft.com"),
};
var folder = Folder.Bind(client, WellKnownFolderName.SentItems);
We had a similar problem: We wanted to use a Service Account to connect to a single mailbox and just doing some stuff with the EWS API (e.g. searching in the GAL) and the full_access_as_app seems like an overkill.
Fortunately it is possible:
Follow the normal "delegate" steps
And use this to get a token via username/password:
...
var cred = new NetworkCredential("UserName", "Password");
var authResult = await pca.AcquireTokenByUsernamePassword(new string[] { "https://outlook.office.com/EWS.AccessAsUser.All" }, cred.UserName, cred.SecurePassword).ExecuteAsync();
...
To make this work you need to enable the "Treat application as public client" under "Authentication" > "Advanced settings" because this uses the "Resource owner password credential flow". (This SO answer helped me alot!)
With that setup we could use a "tradional" username/password way, but using OAuth and the EWS API.
You can protect your client application with either a certificate or a secret. The two permissions that I needed to get this to work were Calendars.ReadWrite.All and full_access_as_app. I never tried acquiring my token via PostMan, but use AcquireTokenAsync in Microsoft.IdentityModel.Clients.ActiveDirectory. In that call, the resource parameter I use is https://outlook.office365.com/. It's pretty simple once you know all the little twists and turns. And full disclosure: I was one lost puppy until MSFT support helped me through this. The doc on the web is often outdated, conflicting, or at best, confusing.
You need to register your app in Azure and use certificate based authentication. https://blogs.msdn.microsoft.com/emeamsgdev/2018/09/11/authenticating-against-exchange-web-services-using-certificate-based-oauth2-tokens/
I run into the same issue while following Microsoft official docs for OAuth 2.0 client credentials flow
According to the Microsoft identity platform and the OAuth 2.0 client credentials flow, the scope "should be the resource identifier (application ID URI) of the resource you want, affixed with the .default suffix" (see default scope doc).
So the question is how to convert https://outlook.office.com/EWS.AccessAsUser.All into the resource identifier.
Experimentally I manage to make it working using scope=https://outlook.office365.com/.default. I granted full_access_as_app (Office 365 Exchange Online / Application permissions) and got administrator consent for it.
I did face this issue while implementing OAuth for EWS. My application is not using EWS Managed API. Here is what all I did to make it working.
Added permission Office 365 Exchange Online > full_access_as_app to application.
Acquired access token for scope https://outlook.office365.com/.default.
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
form-data = {
client_id,
client_secret,
grant_type: 'client_credentials',
scope: 'https://outlook.office365.com/.default',
};
Added access token as Authorization header and ExchangeImpersonation SOAP header to the request.
<SOAP-ENV:Header>
<t:ExchangeImpersonation>
<t:ConnectingSID>
<t:PrimarySmtpAddress>user#domain.com</t:PrimarySmtpAddress>
</t:ConnectingSID>
</t:ExchangeImpersonation>
</SOAP-ENV:Header>
Late answer, but since this seems to come up, and I was just working with this... why not.
If you use Microsoft's v2.0 URLs for OAUTH2 (https://login.microsoftonline.com/common/oauth2/v2.0/authorize and .../common/oauth2/v2.0/token) then the scope for Office 365 EWS is:
https://outlook.office365.com/EWS.AccessAsUser.All
You'll probably want to combine this scope with "openid" (to get the signed in user's identity) and "offline_access" (to get a refresh token). But then offline_access may not be necessary when using client credentials (because you don't have to prompt a human user for them every time you need an access token).
In other words:
params.add("client_id", "...")
...
params.add("scope", "openid offline_access https://outlook.office365.com/EWS.AccessAsUser.All")
If using v1 OAUTH2 URLs (https://login.microsoftonline.com/common/oauth2/authorize and .../common/oauth2/token) then you can use a "resource" instead of a "scope". The resource for Office 365 is https://outlook.office365.com/.
Or in other words:
params.add("resource", "https://outlook.office365.com/")
Note that in the latter case, you're not asking for any scopes (it's not possible to combine "resource" with scopes). But the token will automatically cover offline_access and openid scopes.
I used this method successfully:
Install Microsoft Authentication Library module ( MSAL.PS)
https://www.powershellgallery.com/packages/MSAL.PS/4.2.1.3
Configure Delegate Access as per MSFT instructions: https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
Configure ApplicationImpersonation for a service account as normal
Grab your token
$cred = Get-Credential
$clientid = ""
$tenantid = ""
$tok = Get-MsalToken -ClientId $clientid -TenantId $tenantid -UserCredential $cred -Scopes "https://outlook.office.com/EWS.AccessAsUser.All"
I have a .NET 4.6.2 Windows client application which needs to get an authentication token from our on-premise ADFS server and use it to call an ASP.NET Core REST API. It's client name, id (GUID) and re-direct URI have been registered with ADFS. I am using the latest ADAL (v3.13) library to facilitate the authentication. I am attempting to get a token as demonstrated in the ADAL sample code like this:
AuthenticationContext authenticationContext = new AuthenticationContext("https://<adfs-sts-server>/<rest-api-host>", false);
var result = authenticationContext.AcquireTokenAsync(<rest-api-resource-uri>, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto));
The AcquireTokenAsync call returns an error, saying: The browser based authentication dialog failed to complete. Reason: The server has not found anything matching the requested URI (Uniform Resource Identifier).
Can anyone tell me:
Is the "requested URI" refered to in the error the https://<adfs-sts-server>/<rest-api-host> or <rest-api-resource-uri>?
Do I need to register <rest-api-host> or <rest-api-resource-uri> with ADFS in some way, and if so how?
Any other information I need to get this to work?
Thanks!
Peter
Using Active Directory Federation Services (ADFS) to provide authentication for on-premise endpoints from a Windows Client
Configuring ADFS
There are 2 parts to configuring ADFS.
Register the client application with ADFS
ADFS needs to be able to identify the application requesting user authentication, whether it be a service, WPF application, Web client or Office Add-in. I have gone generic and added the following client, which we can use for most of our C# requests; we may need to register a new client with different callback for Web clients.
Use one of the many tools out there to generate a GUID for the client ID.
* CLIENT_ID and APP_NAME should be unique.
* For a web client the redirect URI is where the auth service will redirect your call after authenticating the user. It should be an endpoint where you can process the token and continue with your client application. The redirect URI is not really used with rich clients/services/add-ins.
CLIENT_ID = 26E54EC9-7988-4DAE-A527-483A8A78B1C6
APP_NAME = Investplus
DESCRIPTION = Invest+ rich client suite
REDIRECT_URI = https://server/redirect-adfs.html
Instructions for Client registration
(may be possible in a wizard, but this is what I found on the web and it worked fo us)
Log on to the AD FS server as administrator and open a Windows PowerShell command window.
Enter the following command. In Windows PowerShell
Add-AdfsClient -ClientId <CLIENT_ID> -Name <APP_NAME> -RedirectUri <REDIRECT_URI>
Register the resource to be accessed ('Relying Party' in ADFS speak)
I found this link useful, it takes you through the steps of the wizard for setting up a relying party.
Instructions for Relying Party registration
The administrator on the server team will need to use the ADFS Add Relying Party Trust Wizard, and under the "Select Data Source" step select Enter data about the relying party manually.
Values you need to supply for this wizard:
DISPLAY_NAME = "MyInvestApi" (Unique display name for this Relying party)
PROFILE = "AD FS Profile"
ENABLE_SUPPORT_FOR_WS-FEDERATION_PASSIVE_PROTOCOL = true
URL = "https://server/api" (Unique URL for this RP)
ADD_ONE_OR_MORE_IDENTIFIERS = eg. "urn:myInvestApi" and "https://server/api"
ACCEPT_REMAINING_DEFAULTS
when given the opportunity, Add Claim Rules:
SEND_LDAP_ATTRIBUTES_AS_CLAIMS = true
ATTRIBUTE_STORE = Active Directory
SELECT_USEFUL_ATTRIBUTES = User-Principal-Name; Email; Display-Name
Configuring/Coding the Client application
Microsoft provides Active Directory Authentication Libraries (ADAL) for a range of platforms and languages from C# to Javascript, and from iOS to Cordova to Node.
The API exposed has changed significantly in each major version: I am using the latest C# library, currently 3.13.5.
The library makes the coding very simple, just a few lines; where I had problems was:
I couldn't find an explanation of what URL to use for the ADFS
Secure Token Service (STS)
I couldn't find documentation of the whole process as I am doing here (most documentation focussed on Azure FS), I struggled to work out
how the values provided to ADFS for Client and Relying party mapped
to the values used in the code.
What is the ADFS endpoint/URL to use in code?
Microsoft's best practice is to name your ADFS/STS server URL https://sts.domain.com (some people use https://adfs.domain.com, ask your server admins). However, if you try to hit this from a browser you'll get a 404 - Not found and trying to retrieve a token in the code, the ADAL library reports:
The browser based authentication dialog failed to complete. Reason: The server has not found anything matching the requested URI (Uniform Resource Identifier).
This is how I found the endpoint to use:
ADFS pubishes federation metadata at 'https://sts.domain.com/federationmetadata/2007-06/federationmetadata.xml'
Extract this file and open in a text editor.
When configuring the Relying Party, we specified "Enable Support for WS-Federation Passive Protocol" when specifying our resource endpoint, so search the XML for PassiveRequestorEndpoint.
Use the <Address> from this node - in my case https://sts.domain.com/adfs/ls/. I don't know if this will always be the value, or if it is specified when ADFS is setup and therefore potentially different per site.
What other values to use in the code?
We want our client app to retrieve a JSON Web Token (JWT) from ADFS which we can pass to our protected resource for authentication/authorization purposes.
At its most simple, the access token can be retrieved in 3 lines of code + configuration, and this will show how to translate what we have configured in ADFS to the values required by ADAL:
var stsEndpoint = "https://sts.domain.com/adfs/ls/";
var relyingPartyIdentifier = "urn:myInvestApi"; // Tenant in Azure AD speak, but this is an on-premise service
var authority = stsEndpoint + relyingPartyIdentifier;
var restResourceUrl = "https://server/api";
var redirectUri = "https://server/redirect-adfs.html";
const string CLIENT_ID = "26E54EC9-7988-4DAE-A527-483A8A78B1C6";
AuthenticationContext authenticationContext = new AuthenticationContext(authority, false);
var asyncRequest = authenticationContext.AcquireTokenAsync(restResourceUrl, CLIENT_ID, redirectUri, new PlatformParameters(PromptBehavior.Auto));
var accessToken = asyncRequest.Result.AccessToken;
Useful references
ASP.NET Core Token Authentication Guide
ADAL - Native App to REST service - Authentication with ACS via Browser Dialog
Create a line-of-business Azure app with AD FS authentication
OAuth 2 Simplified
To issue the token for the web API, we need to make the ADFS to aware it by creating a relying party trust for the web API. And when we add a replying party we need to specify the identifiers for the replying party like figure below(Windows Server 2012 R2):
Then we can use this identifiers as the resource URI to acquire the token for this replying party. Please ensure that the resource URI is correct as you config like figure above.
And here is an article about developing with ADFS using OAuth:
Developing Modern Applications using OAuth and Active Directory Federation Services
Depending on the version of asdf, you may be able to use 'discovery' to obtain the endpoints to use.
Have a look at this post for more details: http://www.cloudidentity.com/blog/2015/08/21/openid-connect-web-sign-on-with-adfs-in-windows-server-2016-tp3/
I've created a web application that uses the OAuth authentication and universal connectors as explained in this tutorial, and started to fiddle around a little to add support for other providers like Yahoo and LinkedIn. So the authentication part works and users are created in the asp.net Membership provider. Also, all the providers return the accesstoken which I supposedly can use to retrieve more information regarding the user.
I'd really like to acquire the profile image, but it seems every provider has a different way of requesting this information. Twitter even describes a way to authorise every request by changing the HTTP header information.
Whilst reading this information on the websites of the various providers I was wondering whether this functionality isn't also already included somewhere in DotNetOpenAuth.AspNet or Microsoft.AspNet.Membership.OpenAuth implementation.
How can I use DotNetOpenAuth.AspNet and/or Microsoft.AspNet.Membership.OpenAuth to request the profile image of the loggedin user using the just acquired accesstoken?
UPDATE in response to Leo's answer
I use the following code to make a call on LinkedIn's API.
string accessToken = extraData["accesstoken"]; // Extra Data received from OAuth containing the accesstoken.
WebRequest request = WebRequest.Create("https://api.linkedin.com/v1/people/~:(id,first-name,last-name,date-of-birth,email-address,picture-url)?oauth2_access_token=" + accessToken);
using (WebResponse response = request.GetResponse())
{
// do something with response here.
}
Error message is "The remote server returned an error: (401) Unauthorized.".
What am I doing wrong?
The answer is simple...you can't use any of these. These are wrappers of OAuth and OAuth only specifies how you can authenticate a user. Now, to request the user's profile photo you will need to use the external provider's own API and you will need most likely a valid access token. So, you will need to use one of these implementations of OAuth to authenticate a user and the recieve an access token, store the access token somewhere (usually a cookie) and then use the access token to make sub-sequent calls to the provider's APIs. Examples and links....
Facebook's Graph API allows you to retrieve users profiles
https://developers.facebook.com/docs/graph-api/quickstart/
notice that all examples in the link above will require you to include the access token in a parameter named access_token, for example
https://graph.facebook.com/me?method=GET&format=json&suppress_http_code=1&access_token={your-access-token}
Google...
https://www.googleapis.com/oauth2/v3/userinfo?access_token={your-access-token}
LinkedIn...
https://api.linkedin.com/v1/people/~:(id,first-name,last-name,date-of-birth,email-address,picture-url)?oauth2_access_token={your-access-token}
You can get more specific information from these providers' websites
Let me know if you have any other doubts I might be able to help you since I have implemented stuff like these before.
Cheers, Leo
Hy guys, we are developing a system which will provide users with access to Google Analytics. I'm trying to implement it in the way so user don't need to enter their Google login credentials on our site, so trying to get it work using their login.
I have a solution which gets analytics using user's email and password. I'm looking for a solution which will not require user's email and password but can not find anything.
How can it be done? any advices or links will be appreciated.
thanks
Ok, guys, after a few days of struggle I finally figured this out. There is no documentation on the Internet and people who had done it before did not want to share their success by some reason. I found this discussion which helped me.
To make it work you will need DotNetOpenAuth from http://www.dotnetopenauth.net/ and gdata from http://code.google.com/p/google-gdata/
so
using DotNetOpenAuth.ApplicationBlock;
using DotNetOpenAuth.OAuth;
using Google.GData.Client;
using Google.GData.Analytics;
In DotNetOpenAuth there is sample project named OAuthConsumer which you need.
Change it to requiest authorization for Analytics:
GoogleConsumer.RequestAuthorization(google, GoogleConsumer.Applications.Analytics);
This will get you Token and Token secret.
You can use them like this:
GOAuthRequestFactory requestFactory = new GOAuthRequestFactory("cp", TokenManager.ConsumerKey); //ConsumerKey actually is the name of web application
requestFactory.ConsumerKey = TokenManager.ConsumerKey;
requestFactory.ConsumerSecret = TokenManager.ConsumerSecret;
requestFactory.Token = AccessToken;
requestFactory.TokenSecret = TokenManager.GetTokenSecret(AccessToken);
requestFactory.UseSSL = true;
AnalyticsService service = new AnalyticsService(requestFactory.ApplicationName); // acually the same as ConsumerKey
service.RequestFactory = requestFactory;
const string dataFeedUrl = "https://www.google.com/analytics/feeds/data";
DataQuery query1 = new DataQuery(dataFeedUrl);
This service you can use like here or here
And the last thing, you WILL NOT be available to try and test it on localhost so you will need a domain which MUST be registered with Google here in order to get consumer key and secret
There's a .NET/C# class for Google Data authentication that can be used to access the Google Analytics Data Export API (since the API is part of the Google Data standard, though you might need to make Google Analytics specific adjustments.)*
The authentication is best managed by creating a Google Registered Application, as this allows you to make the authentication without security warnings (and, for that matter, security lapses).
There are three forms of supported authentication; the 'secure'/passwordless ones are OAuth and AuthSub (which is the Google-proprietary version of OAuth); the hardcoded username and password version is referred to by Google as 'ClientLogin', and is not considered secure or ideal for multiple-user applications.
*(Since you tagged the question .netc#)
Edit: More details on using AuthSub or OAuth with the .NET library:
AuthSubSupport: http://code.google.com/p/google-gdata/wiki/AuthSubSupport
Code Samples on how to use the libraries for OAuth authentication: http://code.google.com/apis/gdata/docs/auth/oauth.html#2LeggedOAuth (Click the .NET tab).
Basics of working with OAuth are here: http://code.google.com/apis/accounts/docs/OpenID.html#working
Authenticating with OAuth: http://code.google.com/apis/accounts/docs/OAuth.html
After you authenticate a user with OAuth, you will have the request token that works like the one you get back from Google's login API. From there, it should be the same as username/password.
I don't think you need to mess with OAuth.
The google analytics api lets you pass credentials. Just start from this data feed example.
http://code.google.com/p/google-gdata/source/browse/trunk/clients/cs/samples/Analytics_DataFeed_Sample/dataFeed.cs
// Configure GA API and do client login Authorization.
AnalyticsService asv = new AnalyticsService("gaExportAPI_acctSample_v2.0");
asv.setUserCredentials(clientUser, clientPass);
Download the client library here
http://code.google.com/apis/analytics/docs/gdata/gdataLibraries.html
To get a feel for data queries, play with this and then copy the values into the example above
http://code.google.com/apis/analytics/docs/gdata/gdataExplorer.html