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

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;
}

Related

Azure Authentication Id is not stable

I am using Azure mobile app services with Xamarin Forms.
In my app, I use web social media authentication (Facebook, Twitter, Google) configured in the azure portal.
I am taking the sid gotten from CurrentClient.Id to match it with users in my Easy Tables. However, for some users, after logging in with the same account and same provider, no match is found in my database because the sid is different! I am 100% sure that it is the same account used to login before, yet I get a different sid. How is that possible? Shouldn't it remain the same with every login or what's the whole point of it then?
You are using Azure App Service Authentication for this. There is a stable ID that is available within the JWT that you pass to the service. You can easily get it from the /.auth/me endpoint (see https://learn.microsoft.com/en-us/azure/app-service/app-service-authentication-how-to#validate-tokens-from-providers )
When you GET /.auth/me with the X-ZUMO-AUTH header set to the authenticationToken returned from the login, the user.userId field will be populated with a stable ID. So, the next question is "how do I add this / compare this within the Node.js backend?" Fortunately, the HOW-TO FAQ for Node.js explicitly answers this. Short version is, use context.user.getIdentity() (an async method) to get the identity, then do something with it:
function queryContextFromUserId(context) {
return context.user.getIdentity().then((data) => {
context.query.where({ id: data.userId });
return context.execute();
});
}
function addUserIdToContext(context) {
return context.user.getIdentity().then((data) => {
context.itme.id = data.userId;
return context.execute();
});
}
table.read(queryContextFromUserId);
table.insert(addYserIdToContext);
table.update(queryContextFromUserId);
table.delete(queryContextFromUserId);
The real question here is "what is in the data block?" It's an object that contains "whatever the /.auth/me endpoint with the X-ZUMO-AUTH header produces", and that is provider dependent.
The mechanism to figure this out.
Debug your client application - when the login completes, inspect the client object for the CurrentUser and get the current token
Use Fiddler, Insomnia, or Postman to GET .../.auth/me with an X-ZUMO-AUTH header set to the current token
Repeat for each auth method you have to ensure you have the formats of each one.
You can now use these in your backend.

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.

Azure active directory v2.0 query for Web API integration on a SharePoint site

We have a SharePoint publishing site with anonymous access hosted on the internet. As per out latest requirements, we need to implement user login (AzureAD, Microsoft personal and work accounts, and more).
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-flows
As per the documentation here, we want to implement this using Web API to get the secure information from the database. We are thinking about using MSAL.js file for user login and logout on the SharePoint and after getting a bearer token we can call the Web API for the additional data from our database.
Standalone Web APIs restriction: “You can use the v2.0 endpoint to build a Web API that is secured with OAuth 2.0. However, that Web API can receive tokens only from an application that has the same Application ID. You cannot access a Web API from a client that has a different Application ID. The client won't be able to request or obtain permissions to your Web API.”
How can we create two applications with same application ID at App Registration Portal? Or should we use the same application ID at SharePoint and Web API’s end?
There is no need to register two application, you only need to one register application. After you register the application, you can using the MSAL library below to get the token to call the web API:
<script class="pre">
var userAgentApplication = new Msal.UserAgentApplication("e5e5f2d3-4f6a-461d-b515-efd11d50c338", null, function (errorDes, token, error, tokenType) {
// this callback is called after loginRedirect OR acquireTokenRedirect (not used for loginPopup/aquireTokenPopup)
})
userAgentApplication.loginPopup(["user.read"]).then(function (token) {
var user = userAgentApplication.getUser();
console.log(token);
// signin successful
}, function (error) {
// handle error
});
</script>
And to protect the web API, you can use the same app and refer the code below:
public void ConfigureAuth(IAppBuilder app)
{
var tvps = new TokenValidationParameters
{
// The web app and the service are sharing the same clientId
ValidAudience = "e5e5f2d3-4f6a-461d-b515-efd11d50c338",
ValidateIssuer = false,
};
// NOTE: The usual WindowsAzureActiveDirectoryBearerAuthenticaitonMiddleware uses a
// metadata endpoint which is not supported by the v2.0 endpoint. Instead, this
// OpenIdConenctCachingSecurityTokenProvider can be used to fetch & use the OpenIdConnect
// metadata document.
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
AccessTokenFormat = new JwtFormat(tvps, new OpenIdConnectCachingSecurityTokenProvider("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration")),
});
}

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.

Can I use Google APIs with MVC 5 Authentication via Google instead of using Google's OAuth 2.0?

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)

Resources