Can I use Google APIs with MVC 5 Authentication via Google instead of using Google's OAuth 2.0? - asp.net-mvc-5

Note, that I have previously written an MVC app according to Google Guidelines, by first setting up a project in Google Developers Console, providing Google Auth 2.0 authentication. Everything worked (not perfect though), but worked.
The Client ID and Client Secret I placed in Web.config. Therefore only one specific user could get his information. But I wanted any user to be able to get
his gmail message and calendar events, so we need this general Authentication model, like the one implemented in MVC 5 as Google Sign-in button. MVC 5 provides built-in functionality to sign in via Google, Facebook, Twitter, etc.
After you sign in via Google option, is it possible to access Google APIs, such as Calendar, Gmail, etc. to get my own events, gmail messages?
Example, I want to get Gmail message, I have this class:
public static MyGmail GetGmail(UserCredential credential)
{
var mygmail = new MyGmail();
var service = new GmailService(new BaseClientService.Initializer { HttpClientInitializer = credential });
var request = service.Users.Messages.List("me");
request.Q = "in:inbox is:unread";
var messages = request.Execute().Messages;
return mygmail;
}
Notice this line?
var service = new GmailService(new BaseClientService.Initializer { HttpClientInitializer = credential });
I need to pass credential to that service.
So I have this action in my controller:
public ActionResult Gmail()
{
return PartialView(GmailManager.GetGmail(result.Credential));
}
Notice this parameter: result.Credential?
That is the credentials.
That result object is coming from the Index Action:
public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
if (result == null || result.Credential == null)
{
result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).AuthorizeAsync(cancellationToken);
if (result.Credential == null) return new RedirectResult(result.RedirectUri);
result.Credential.Token.ExpiresInSeconds = expiresInSeconds;
result.Credential.Token.RefreshToken = refreshToken;
}
return View();
}
Notice this line?
result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).AuthorizeAsync(cancellationToken);
The result object is defined like this:
private static AuthorizationCodeWebApp.AuthResult result;
This is how Google OAuth 2.0 works. I am not putting here the AuthCallbackController code for simplicity. Who know what I am talking about and have seen Google Developers Tutorial on authenticating via Google OAuth 2.0, he will understand.
The idea is that after the Authentication (or when you already have the Auth token) you get that result object that has result.Credential property that I can pass as parameter to Google API Service (Gmail, Calendar or any other service) and the authenticated user can retrieve his own gamail messages or calendar events.
Now, to the question - since Authentication via 3-rd party providers such as Google is a part of MVC 5 functionality, the OWIN Katana, Microsoft Implementation (the Google button you can click and Authenticate), I dont need Google OAuth 2.0 code to authenticate a user.
That brings me to the problem - since there is no Google OAuth 2.0 implementation here, I will not be able to get that result object with Credentials, that I need to pass as parameter to Google API service.
But the user is Authenticated already via Google, so that should be double to call Google API Service, just dont know how?
Any ideas? Thanks

I guess not :)) Since there is no AuthorizationCodeWebApp.AuthResult object, that contains result.Credentials that is required to be passed as parameter to Google API Service:
var service = new GmailService(new BaseClientService.Initializer {
HttpClientInitializer = credential });
where credential is of type UserCredential (the one that comes back after Google OAuth2 authorization: AuthorizationCodeWebApp.AuthResult.Credential)

Related

Xamarin MobileServiceClient RefreshUserAsync with Google 403

I am using Azure's MobileServiceClient sdk to authenticate with my server. With the upgrades to 4.x version I am also using Xamarin.Auth to authenticate users with Google and Facebook. When the response comes back from Google I am getting a refresh token. I then call the mobile service sdk like so:
var accessToken = account.Properties["access_token"];
var idToken = account.Properties["id_token"];
var zumoPayload = new JObject();
zumoPayload["access_token"] = accessToken;
zumoPayload["id_token"] = idToken;
var user = await client.LoginAsync(MobileServiceAuthenticationProvider.Google, zumoPayload, );
This work perfectly fine. What does not work is the call to client.RefreshUserAsync(). That is throwing a 403 every time saying the refresh token is either expired or no longer valid even when I call that method right after I logged in. I do not see many examples at all using the MobileServiceClient 4.x sdk and none of them have examples of how to use the refresh token.
I have tried sending that upin the zumo payload as well but it does not work. I have tried invalidating my user on Google (I am getting the refresh token back), tried logging in through the browser and going to auth/me but the refresh token is not there. Any help would be great!
AFAIK, you could leverage the Xamarin.Auth SDK to independently contact the identity provider and retrieve the access token on your mobile client side, then you need to login with your backend (azure mobile app) along with the token for retrieving the authenticationToken, then you could leverage the authenticationToken to access the resources under your mobile app.
Since you are using Client-managed authentication, for refreshing the new access_token, you need to do it on your mobile client side. I checked Xamarin.Auth and found that there is no method for requesting an access token. You need to refer to Refreshing an access token and implement this feature by yourself. I followed OAuth2Authenticator.cs and created a extension method for requesting an access token as follows:
public static class OAuth2AuthenticatorExtensions
{
public static Task RefreshAccessTokenAsync(this OAuth2Authenticator authenticator, Account account)
{
var dics = new Dictionary<string, string>
{
{"refresh_token",account.Properties["refresh_token"]},
{"client_id", authenticator.ClientId},
{"grant_type", "refresh_token"}
};
if (!string.IsNullOrEmpty(authenticator.ClientSecret))
{
dics["client_secret"] = authenticator.ClientSecret;
}
return authenticator.RequestAccessTokenAsync(dics).ContinueWith(task =>
{
if (task.IsFaulted)
{
//todo:
}
else
{
authenticator.OnRetrievedAccountProperties(task.Result);
}
});
}
}
Additionally, if you leverage Server-managed authentication with Microsoft.Azure.Mobile.Client, then you could leverage RefreshUserAsync for refreshing the access token, at this point your previous access_token, clientId are stored on azure, and your mobile app backend would directly communicate with Google's OAuth 2.0 endpoint and request a new access token for you and update the token store on Azure. For more details about token store within App Service, you could follow here.

Is it possible to use Azure Mobile App and Azure AD B2C to authenticate localhost web?

I know that local debugging using tokens is possible using http://www.systemsabuse.com/2015/12/04/local-debugging-with-user-authentication-of-an-azure-mobile-app-service/. Would it be possible to go to thesite.com/.auth/login/aad and login and use that cookie for localhost (for testing the web app - not the mobile app)?
I am currently using the .auth/login/aad cookie to authenticate Nancy. I do by generating a ZumoUser out of the Principal.
Before.AddItemToEndOfPipeline(UserToViewBag);
and
internal static async Task<Response> UserToViewBag(NancyContext context, CancellationToken ct)
{
var principal = context.GetPrincipal();
var zumoUser = await ZumoUser.CreateAsync(context.GetPrincipal());
context.ViewBag.User = zumoUser;
context.Items["zumoUser"] = zumoUser;
var url = context.Request.Url;
if (zumoUser.IsAuthenticated)
{
_logger.DebugFormat("{0} requested {1}", zumoUser, url.Path);
}
else
{
_logger.DebugFormat("{0} requested {1}", "Anonymous", url.Path);
}
return null;
}
Yes. You need to read "the book" as it is a complex subject. The book is available open source at http://aka.ms/zumobook and the content you want is in Chapter 2.
Would it be possible to go to thesite.com/.auth/login/aad and login and use that cookie for localhost (for testing the web app - not the mobile app)?
No, this is impossible. The JWT token verification is based on the stand protocol(OpenId connect or Oauth 2) we can follow. But there is no official document or SDK about the the cookie issued by the Easy Auth verification.

ServiceStack OAuth2 mobile native authentication

I need to log on through OAuth 2 how can I do that without using WebView in Android?
Thanks.
In the latest v4.5.7 of ServiceStack you'll be able to login into Twitter, Facebook or Github using their SDKs and previous saved access tokens.
Authentication via AccessToken is also made available to OAuth2 providers in the same way where you can authenticate directly by adding the AccessToken to the Authenticate Request DTO, e.g:
var request = new Authenticate
{
provider = "GoogleOAuth",
AccessToken = GoogleOAuthAccessToken,
};
var response = client.Post(request);
response.PrintDump();
Although you will first need to retrieve the AccessToken which typically requires opening a WebView to capture Users consent.
For other OAuth2 providers other than Google Auth you will need to provide an implementation of VerifyAccessToken that returns a boolean that determines whether the AccessToken is valid or not, e.g:
new MyOAuth2Provider {
VerifyAccessToken = accessToken => MyValidate(ConsumerKey,accessToken),
}
This is different for each OAuth provider where some don't provide an API that lets you determine whether the AccessToken is valid with your App or not.

How to get X-Zumo-auth token in Azure Mobile service

I am planning to automate some scenarios in my app. basically 5 different users calls some apis on using Mobile client app. Now in order to simulate that,I need to call my server apis with X-ZUMO-Auth, just wandering how can I gt the X-Zumo-auth for 5 different test users. I tried calling https:///.auth/login/facebook/ and then https:///.auth/me which gives me oath token for Facebook.
Use the following function to create a token valid for 24h.
You need to have your SigningKey (if it's the newer AppServices mobile you can just use Environment.GetEnvironmentVariable("WEBSITE_AUTH_SIGNING_KEY") instead.
public static string CreateToken(string userid)
{
JwtSecurityToken token = AppServiceLoginHandler.CreateToken(new Claim[] { new Claim(JwtRegisteredClaimNames.Sub, userid) },
ConfigurationManager.AppSettings["SigningKey"],
ConfigurationManager.AppSettings["ValidAudience"],
ConfigurationManager.AppSettings["ValidIssuer"],
TimeSpan.FromHours(24));
return token.RawData;
}

Getting username and group info from Azure using adal4j

I am developing a mobile app in which I need to authenticate a user against Azure AD. Basically the user will be prompted their organisational email and password, which the mobile phone app sends to the backend server which will authenticate.
I have the 'public-client-app-sample' of 'azure-activedirectory-library-for-java' working, and can authenticate against 'graph.windows.net':
private static AuthenticationResult getAccessTokenFromUserCredentials(
String username, String password) throws Exception {
AuthenticationContext context = null;
AuthenticationResult result = null;
ExecutorService service = null;
try {
service = Executors.newFixedThreadPool(1);
context = new AuthenticationContext(AUTHORITY, false, service);
Future<AuthenticationResult> future = context.acquireToken(
"https://graph.windows.net", CLIENT_ID, username, password,
null);
result = future.get();
} finally {
service.shutdown();
}
if (result == null) {
throw new ServiceUnavailableException(
"authentication result was null");
}
return result;
}
However, this does not return any userInfo (is null), and I can't figure out at this moment how to query to get a list with groups the user belongs to?
Do I just do manual lookups using the API using the tokens obtained from Adal4j, or is there a provided function within the library?
I am only starting with Azure, so it might be obvious, I might just be looking in the wrong places. I tried e.g. 'https://graph.windows.net/xxx.com/groups?api-version=1.5' but get 'Resource 'https://graph.windows.net/xxx.com/groups?api-version=1.5' is not registered for the account.'
First, you're absolutely right, adal4j was failing to return UserInfo. The reason for this was that the token request did not include the scope=openid parameter, which is required if the caller wants an id_token in the response. I opened an issue, and it has already been resolved. So, an updated copy of adal4j will fix your first issue of not getting UserInfo.
Now, regarding group membership for the current user: Normally, I would recommend that you simply configure you application to return the groups claim. This can be done very easily by changing the application manifest (downloaded and uploaded via the Azure portal, under the Application's configuration page) to include:
"groupMembershipClaims": "All",
Unfortunately, adal4j does not yet include the groups claim in the result of getUserInfo(), so that probably won't work much for you (issue opened, it really depends on how quickly it gets implemented, or if you want to implement youself).
Regardless, because it is possible for there to be too many groups to include in the token (indicated by , your application should always be able to use the AAD Graph API to retrieve the full set of groups the user is a member of.
And that brings me to the last point: adal4j does not implement a client of the Azure AD Graph API. So yes, you would have to implement that yourself (or perhaps use/modify an existing OData client).
(You can read more about Group Claims in this Azure AD blog post.)

Resources