Local accounts in Microsoft Azure Mobile Services
- Tutorial
Another poorly described topic about Microsoft Azure Mobile Services is authorization, which is also set up only in the latest versions. Of course, from the earliest versions there was the MobileServiceAuthenticationProvider enumeration, which made it possible to perform authorization using one of the specified methods in a simple way. But this set is hardly the most convenient solution for users. There are two possible directions for expansion - adding new versions of the OpenId mechanism or your own authorization mechanism. Next, the second option will be considered.
To begin with, if you use a too old template from Visual Studio to create a project (for example, 2nd update for 2013), then the version of NuGet for WindowsAzure.MobileServices.Backend may not support the solution discussed below. At the time of writing the article with the latest version 1.0.439, there were difficulties with compatibility with new versions of other modules, so the following set is used here:
First, create the classes DemoCredentials (inherited from ProviderCredentials) and LocalLoginProvider (inherited from LoginProvider) and declare them as follows:
The ConfigureMiddleware method is not needed in this case, because it is intended for external authorization.
Next, create an API controller and declare the main authorization method in it, which will return the LoginResult data type. To simplify the example, there will be no verification of authorization parameters in it, I believe that it will not be difficult for readers to add a method for checking them that is necessary for a specific task.
The LoginResult class contains a very important parameter - AuthenticationToken, which is needed on the client side. It is issued by the server for the time specified in the parameters and determines the fact of the presence of authorization on behalf of a specific user - in this case, “Demo: fakeUser”.
The Handler property is declared in the controller as follows:
After that, Autofac will set its required value.
Next, consider an example client application based on Xamarin.Android. You can use one assembly, but in order to demonstrate cross-platform capabilities, PCL with profile 111 will be used. This profile is supported in Xamarin.Android, Xamarin.iOS and WinStore applications. To simplify the example, a reduced number of application layers will be used, and the implementation of the user interface will exclude activity lifecycle processing. Run the command:
Then we implement the authorization method:
After that, when calling any controller method that requires authorization, the User property of the controller will contain the specified value "Demo: fakeUser". The remaining parts of the client application contain lines of code that are common in other applications; for a more detailed study, the source code archive of the example can be downloaded here .
To begin with, if you use a too old template from Visual Studio to create a project (for example, 2nd update for 2013), then the version of NuGet for WindowsAzure.MobileServices.Backend may not support the solution discussed below. At the time of writing the article with the latest version 1.0.439, there were difficulties with compatibility with new versions of other modules, so the following set is used here:
Install-Package AutoMapper -Version 3.2.1
Install-Package System.IdentityModel.Tokens.Jwt -Version 3.0.2
Install-Package Microsoft.Owin.Security -Version 2.1.0
Install-Package Microsoft.Owin.Security.OAuth -Version 2.1.0
Install-Package Microsoft.Owin.Security.Cookies -Version 2.1.0
Install-Package Microsoft.Owin.Security.Jwt -Version 2.1.0
Install-Package Microsoft.Owin.Security.ActiveDirectory -Version 2.1.0
Install-Package Microsoft.Owin.Security.Facebook -Version 2.1.0
Install-Package Microsoft.Owin.Security.Google -Version 2.1.0
Install-Package Microsoft.Owin.Security.Twitter -Version 2.1.0
Install-Package Microsoft.Owin.Security.MicrosoftAccount -Version 2.1.0
Install-Package WindowsAzure.MobileServices.Backend.Entity -Version 1.0.405
First, create the classes DemoCredentials (inherited from ProviderCredentials) and LocalLoginProvider (inherited from LoginProvider) and declare them as follows:
public class DemoCredentials: ProviderCredentials
{
public string AccessToken { get; set; }
public DemoCredentials()
: base(DemoLoginProvider.ProviderName)
{
}
}
public class DemoLoginProvider: LoginProvider
{
public const string ProviderName = "Demo";
public override string Name
{
get { return ProviderName; }
}
public DemoLoginProvider(IServiceTokenHandler tokenHandler)
: base(tokenHandler)
{
}
public override void ConfigureMiddleware(Owin.IAppBuilder appBuilder, Microsoft.WindowsAzure.Mobile.Service.ServiceSettingsDictionary settings)
{
return;
}
public override ProviderCredentials CreateCredentials(System.Security.Claims.ClaimsIdentity claimsIdentity)
{
System.Security.Claims.Claim name = claimsIdentity.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
System.Security.Claims.Claim providerAccessToken = claimsIdentity.FindFirst(ServiceClaimTypes.ProviderAccessToken);
DemoCredentials credentials = new DemoCredentials
{
UserId = this.TokenHandler.CreateUserId(Name, name != null ? name.Value : null),
AccessToken = providerAccessToken != null ? providerAccessToken.Value : null
};
return credentials;
}
public override ProviderCredentials ParseCredentials(Newtonsoft.Json.Linq.JObject serialized)
{
return serialized.ToObject();
}
}
The ConfigureMiddleware method is not needed in this case, because it is intended for external authorization.
Next, create an API controller and declare the main authorization method in it, which will return the LoginResult data type. To simplify the example, there will be no verification of authorization parameters in it, I believe that it will not be difficult for readers to add a method for checking them that is necessary for a specific task.
[HttpPost]
[Route("api/Authentication/Authenticate")]
[AllowAnonymous]
public async Task Authenticate()
{
DemoLoginProvider provider = new DemoLoginProvider(Handler);
System.Security.Claims.ClaimsIdentity claimsIdentity = new System.Security.Claims.ClaimsIdentity();
claimsIdentity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.NameIdentifier, "fakeUser"));
LoginResult loginResult = provider.CreateLoginResult(claimsIdentity, Services.Settings.MasterKey);
return Request.CreateResponse(HttpStatusCode.OK, loginResult);
}
The LoginResult class contains a very important parameter - AuthenticationToken, which is needed on the client side. It is issued by the server for the time specified in the parameters and determines the fact of the presence of authorization on behalf of a specific user - in this case, “Demo: fakeUser”.
The Handler property is declared in the controller as follows:
public IServiceTokenHandler Handler { get; set; }
After that, Autofac will set its required value.
Next, consider an example client application based on Xamarin.Android. You can use one assembly, but in order to demonstrate cross-platform capabilities, PCL with profile 111 will be used. This profile is supported in Xamarin.Android, Xamarin.iOS and WinStore applications. To simplify the example, a reduced number of application layers will be used, and the implementation of the user interface will exclude activity lifecycle processing. Run the command:
Install-Package WindowsAzure.MobileServices
Then we implement the authorization method:
public async Task AuthenticateAsync()
{
LoginResultDTO loginResult = await _channel.InvokeApiAsync("Authentication/Authenticate").ConfigureAwait(false);
MobileServiceUser user = new MobileServiceUser(loginResult.User.UserId)
{
MobileServiceAuthenticationToken = loginResult.AuthenticationToken
};
_channel.CurrentUser = user;
}
After that, when calling any controller method that requires authorization, the User property of the controller will contain the specified value "Demo: fakeUser". The remaining parts of the client application contain lines of code that are common in other applications; for a more detailed study, the source code archive of the example can be downloaded here .