Search code examples
c#azurexamarinxamarin.formscustom-authentication

Xamarin, Azure, customauth and passing parameters


I am in the process of rewritting our app using Xamarin.Forms with a C# backend and I'm trying to use customauth on login. I've got it working to a point but am struggling to pass back to the Xamarin app everything I want from the backend. I'm getting the token and user id but want a bit more.

The backend code on succesfull login seems relatively straightforward:

return Ok(GetLoginResult(body));

where GetLoginResult() is:

private object GetLoginResult(IUser body)
        {
            var claims = new Claim[]
            {
                new Claim(JwtRegisteredClaimNames.Sub, body.username)
            };

            JwtSecurityToken token = AppServiceLoginHandler.CreateToken(
                claims, signingKey, audience, issuer, TimeSpan.FromDays(30));

            accounts account = db.accounts.Single(u => u.username.Equals(body.username));

            return new LoginResult(account)
            {
                authenticationToken = token.RawData,
            };
        }

and the LoginResult class is

public class LoginResult
{

    public LoginResult(accounts account)
    {
        Response = 200;
        CustomerId = account.CustomerId;
        Modules = account.Modules;
        User = new LoginResultUser
        {
            userId = account.id,
            UserName = account.UserName,
            EmployeeId = account.EmployeeId
        };
    }

    [JsonProperty(PropertyName = "Response")]
    public int Response { get; set; }

etc

In the app, I'm calling the customauth as follows:

MobileServiceUser azureUser = await _client.LoginAsync("custom", JObject.FromObject(account));

The result has the token and the correct userid but how can I fill the result with the additional properties passed back by the backend? I've got the backend working and tested using postman and the results I get there are what I want but I've been unable to find out how to get it deserialized in the app.


Solution

  • As I known, for custom auth , MobileServiceClient.LoginAsync would invoke https://{your-app-name}.azurewebsites.net/.auth/login/custom. When using ILSPy you could find that this method would only retrieve the user.userId and authenticationToken from the response to construct the CurrentUser of your MobileServiceClient. Per my understanding, you could leverage MobileServiceClient.InvokeApiAsync to retrieve the additional user info after the user has logged in successfully. Additionally, you could try to follow this toturial for other possible approaches.

    UPDATE

    You could use InvokeApiAsync instead of LoginAsync to invoke the custom login endpoint directly, then retrieve the response and get the additional parameters as follows:

    When logged successfully, I added a new property userName and response the client as follows:

    enter image description here

    For the client, I added a custom extension method for logging and retrieve the additional parameters as follows:

    enter image description here

    Here are the code snippet, you could refer to them:

    MobileServiceLoginExtend.cs

    public static class MobileServiceLoginExtend
    {
        public static async Task CustomLoginAsync(this MobileServiceClient client, LoginAccount account)
        {
            var jsonResponse = await client.InvokeApiAsync("/.auth/login/custom", JObject.FromObject(account), HttpMethod.Post, null);
            //after successfully logined, construct the MobileServiceUser object with MobileServiceAuthenticationToken
            client.CurrentUser = new MobileServiceUser(jsonResponse["user"]["userId"].ToString());
            client.CurrentUser.MobileServiceAuthenticationToken = jsonResponse.Value<string>("authenticationToken");
    
            //retrieve custom response parameters
            string customUserName = jsonResponse["user"]["userName"].ToString();
        }
    }
    

    Login processing

    MobileServiceClient client = new MobileServiceClient("https://bruce-chen-002-staging.azurewebsites.net/");
    var loginAccount = new LoginAccount()
    {
        username = "brucechen",
        password = "123456"
    };
    await client.CustomLoginAsync(loginAccount);