Implement user authentication in Windows Azure Mobile Services

On Windows Azure Mobile Services, there is currently no way to authenticate user and view feature request

http://feedback.azure.com/forums/216254-mobile-services/suggestions/3313778-custom-user-auth

It will not come soon.

With the .NET backend and .NET application, how do you implement user authentication so you don’t have to use Facebook, Google or your other current providers?

There are many partially completed tutorials on how to do this with the JS and iOS and Android backends, but where are the .NET examples?

+6
source share
2 answers

I finally worked on the solution, with some help from the articles listed below, some intellisense and some trial and error.

How does WAMS work?

At first I wanted to describe that WAMS is in a very simple form, since this part of me was a little embarrassed until it finally clicked. WAMS is just a collection of pre-existing technologies packaged for quick deployment. What you need to know for this scenario:

enter image description here

As you can see, WAMS is just a container for WebAPI and other things about which I will not go into details here. When you create a new mobile service in Azure, you can download the project containing the WebAPI. The example they use is TodoItem, so you will see the code for this scenario through the project.

Below you can download this example (I just made an application for Windows Phone 8)

enter image description here

I could continue on about this, but this tutorial will help you get started:

http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-windows-store-dotnet-get-started/

Setting up a WAMS project

You will need your MasterKey and ApplicationKey. You can get them from Azure Portal by clicking on the Mobile Services app and pressing the "Manage" keys at the bottom

enter image description here

The project that you just downloaded, in the Controllers folder, I just created a new controller called AccountController.cs and inside I put

public HttpResponseMessage GetLogin(String username, String password) { String masterKey = "[enter your master key here]"; bool isValidated = true; if (isValidated) return new HttpResponseMessage() { StatusCode = HttpStatusCode.OK, Content = new StringContent("{ 'UserId' : 'F907F58C-09FE-4F25-A26B-3248CD30F835', 'token' : '" + GetSecurityToken(new TimeSpan(1,0, 0), String.Empty, "F907F58C-09FE-4F25-A26B-3248CD30F835", masterKey) + "' }") }; else return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Username and password are incorrect"); } private static string GetSecurityToken(TimeSpan periodBeforeExpires, string aud, string userId, string masterKey) { var now = DateTime.UtcNow; var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var payload = new { exp = (int)now.Add(periodBeforeExpires).Subtract(utc0).TotalSeconds, iss = "urn:microsoft:windows-azure:zumo", ver = 2, aud = "urn:microsoft:windows-azure:zumo", uid = userId }; var keyBytes = Encoding.UTF8.GetBytes(masterKey + "JWTSig"); var segments = new List<string>(); //kid changed to a string var header = new { alg = "HS256", typ = "JWT", kid = "0" }; byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None)); byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None)); segments.Add(Base64UrlEncode(headerBytes)); segments.Add(Base64UrlEncode(payloadBytes)); var stringToSign = string.Join(".", segments.ToArray()); var bytesToSign = Encoding.UTF8.GetBytes(stringToSign); SHA256Managed hash = new SHA256Managed(); byte[] signingBytes = hash.ComputeHash(keyBytes); var sha = new HMACSHA256(signingBytes); byte[] signature = sha.ComputeHash(bytesToSign); segments.Add(Base64UrlEncode(signature)); return string.Join(".", segments.ToArray()); } // from JWT spec private static string Base64UrlEncode(byte[] input) { var output = Convert.ToBase64String(input); output = output.Split('=')[0]; // Remove any trailing '='s output = output.Replace('+', '-'); // 62nd char of encoding output = output.Replace('/', '_'); // 63rd char of encoding return output; } 

You can replace what's in GetLogin with your own validation code. After checking, it will return the security token (JWT), which is required.

If you are testing a local host, do not forget to go into your web.config file and fill in the following keys

 <add key="MS_MasterKey" value="Overridden by portal settings" /> <add key="MS_ApplicationKey" value="Overridden by portal settings" /> 

Here you must enter your main and application keys. They will be canceled when they are downloaded, but they must be entered if you are doing everything locally.

At the top of the TodoItemController, add the AuthorizeLevel attribute, as shown below.

 [AuthorizeLevel(AuthorizationLevel.User)] public class TodoItemController : TableController<TodoItem> 

You will need to change most of the functions in your TodoItemController, but here is an example of the Get All function.

  public IQueryable<TodoItem> GetAllTodoItems() { var currentUser = User as ServiceUser; Guid id = new Guid(currentUser.Id); return Query().Where(todo => todo.UserId == id); } 

Just a note. I am using UserId as Guid (uniqueidentifier) ​​and you need to add this to the todo model definition. You can make UserId any type you want, for example. Int32

Windows Phone / Store App

Please note that this is just an example, and you should clear the code in your main application after it works.

In your client application

Install NuGet Package: Windows Azure Mobile Services

Go to App.xaml.cs and add this to the beginning

  public static MobileServiceClient MobileService = new MobileServiceClient( "http://localhost:50527/", "[enter application key here]" ); 

In MainPage.xaml.cs I created

 public class Token { public Guid UserId { get; set; } public String token { get; set; } } 

In the main class add the Authenticate function

  private bool Authenticate(String username, String password) { HttpClient client = new HttpClient(); // Enter your own localhost settings here client.BaseAddress = new Uri("http://localhost:50527/"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = client.GetAsync(String.Format("api/Account/Login?username={0}&password={1}", username, password)).Result; if (response.StatusCode == System.Net.HttpStatusCode.OK) { var token = Newtonsoft.Json.JsonConvert.DeserializeObject<Token>(response.Content.ReadAsStringAsync().Result); App.MobileService.CurrentUser = new MobileServiceUser(token.UserId.ToString()); App.MobileService.CurrentUser.MobileServiceAuthenticationToken = token.token; return true; } else { //Something has gone wrong, handle it here return false; } } 

Then in the function Main_Loaded

  private void MainPage_Loaded(object sender, RoutedEventArgs e) { Authenticate("test", "test"); RefreshTodoItems(); } 

If you have breakpoints in the WebAPI, you will see that it is logged in, get a token, then go back to ToDoItemController and the currentUser will be populated with UserId and token.

You will need to create your own login page, because with this method you cannot use the automatically created with other identity providers. However, I prefer to create my own login screen.

Any other questions let me know in the comments and I will help if I can.

Safety note

Remember to use SSL.

References

[] http://www.thejoyofcode.com/Exploring_custom_identity_in_Mobile_Services_Day_12_.aspx

[] http://www.contentmaster.com/azure/creating-a-jwt-token-to-access-windows-azure-mobile-services/

[] http://chrisrisner.com/Custom-Authentication-with-Azure-Mobile-Services-and-LensRocket

+20
source

This is exactly how you do it. This man needs 10 stars and 5 boxes of beer!

One thing, I used LoginResult's mobile service to login, for example: var token = Newtonsoft.Json.JsonConvert.DeserializeObject (response.Content.ReadAsStringAsync (). Result);

Hope to get it in Android now!

+1
source

Source: https://habr.com/ru/post/973922/


All Articles