0% found this document useful (0 votes)
81 views10 pages

Xamarin Essentials - Cool Coders: Doumer - Me

This document discusses implementing JWT social authentication with ASP.NET Core and Xamarin Essentials. It will cover setting up social authentication on Facebook and Google, getting user information from social logins, and generating JWT tokens. Key aspects include using the Xamarin Essentials Web Authenticator API for authentication in mobile apps, and adding social login options and JWT authentication to an ASP.NET Core API.

Uploaded by

hsuyip
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
81 views10 pages

Xamarin Essentials - Cool Coders: Doumer - Me

This document discusses implementing JWT social authentication with ASP.NET Core and Xamarin Essentials. It will cover setting up social authentication on Facebook and Google, getting user information from social logins, and generating JWT tokens. Key aspects include using the Xamarin Essentials Web Authenticator API for authentication in mobile apps, and adding social login options and JWT authentication to an ASP.NET Core API.

Uploaded by

hsuyip
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

JWT Social auth with ASP.net core and Xamarin Essentials - Cool Coders about:reader?url=https://doumer.me/jwt-social-auth-with-asp-net-core...

doumer.me

JWT Social auth with ASP.net core and


Xamarin Essentials - Cool Coders
14-17 minutes

Uncategorized ,

08 Nov

Hello friends, here is my second post about social auth with


Xamarin Forms and ASP.net core. The previous method, though
functional is kind of old and less recommended than this new
approach. A few month ago, a new feature was added to Xamarin
Essentials, permitting us to easily implement authentication with a
back-end API (not only ASP.net core). This feature is better than
previous authentication mechanisms, primarily because it avoids us
from adding our application credentials inside our mobile app’s
source code. And also, it is very easy to implement. Together, we
will not only go through the process of implementing JWT social
auth with ASP.net core and Xamarin Essentials, but we will also
highlight and solve some difficulties you might face when
implementing this feature in a real-world application. So, lets dive
in.

Xamarin Essentials is constantly improving, and one of the features

1 of 10 11/28/2020, 4:08 PM
JWT Social auth with ASP.net core and Xamarin Essentials - Cool Coders about:reader?url=https://doumer.me/jwt-social-auth-with-asp-net-core...

which was added a few months ago is the Web Authenticator API.
This feature provides an abstraction layer over the process of
integrating authentication, calling the web browser, Managing
redirects e.t.c in our Xamarin App.

HERE is the source code for this post.

What we will do

Setup Social authentication with the Back-end and mobile app

Getting user information from social media

Adding Aspnetcore identity and Generating our own JWT tokens

This post is associated to the video on my channel.

JWT Social Auth with Asp.net Core and Xamarin Essentials

Let’s setup our apps on social media

First, we have to setup our client app on social media, in our case
we use Google and Facebook.

Then we get our app secrets and ids. This process is simple, and
well documented so, I just highlighted how to setup your redirect
URLs properly in the video associated to this post.

Then we create an ASP net core project and setup Cookie and
JWT authentication. Adding Google and Facebook auth with the
Credentials we saved earlier

1 services

2 .AddAuthentication(options =>

3 {

4 ///TODO: If you plan to use both cookie and JWT auth on this
API, you can use this attribute
5

6 ///[Authorize(AuthenticationSchemes =
JwtBearerDefaults.AuthenticationScheme)]
7
options.DefaultAuthenticateScheme =
8
JwtBearerDefaults.AuthenticationScheme;
9
options.DefaultScheme =
10 JwtBearerDefaults.AuthenticationScheme;

11 options.DefaultChallengeScheme =
12 JwtBearerDefaults.AuthenticationScheme;

13 })

14 .AddCookie(options =>

2 of 10 11/28/2020, 4:08 PM
JWT Social auth with ASP.net core and Xamarin Essentials - Cool Coders about:reader?url=https://doumer.me/jwt-social-auth-with-asp-net-core...

15 {

16 options.Events.OnRedirectToLogin =
options.Events.OnRedirectToAccessDenied = context =>
17
{
18

19 context.Response.StatusCode =
StatusCodes.Status401Unauthorized;
20
return Task.CompletedTask;
21
};
22
})
23
.AddJwtBearer(cfg =>
24
{
25
cfg.RequireHttpsMetadata = false;
26
cfg.SaveToken = true;
27
cfg.TokenValidationParameters = new
28
TokenValidationParameters
29
{
30
ValidIssuer = Configuration["JwtIssuer"],
31
ValidAudience = Configuration["JwtIssuer"],
32
IssuerSigningKey = new
33 SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtKey"])),

34 ClockSkew = TimeSpan.Zero // remove delay of token when

35 expire

36 };

37 })

38 .AddFacebook(facebook =>

39 {

40 facebook.AppId =
Configuration["Authentication:Facebook:AppId"];
41
facebook.AppSecret =
42
Configuration["Authentication:Facebook:AppSecret"];

facebook.SaveTokens = true;

})

.AddGoogle(google =>

google.ClientSecret =

3 of 10 11/28/2020, 4:08 PM
JWT Social auth with ASP.net core and Xamarin Essentials - Cool Coders about:reader?url=https://doumer.me/jwt-social-auth-with-asp-net-core...

Configuration["Authentication:Google:ClientSecret"];

google.ClientId =
Configuration["Authentication:Google:ClientId"];

google.SaveTokens = true;

Note: If you are using both Cookie and JWT auth scheme in your
API, you can chose which scheme to use in your controllers using
this attribute.

[Authorize(AuthenticationSchemes =
JwtBearerDefaults.AuthenticationScheme)]

Social Authentication Process

The mobile authentication process is simple and will take place as


follows:

Xamarin Essentials calls our API passing the scheme (Facebook or


Google in our case) depending on which social media the user
wants to authenticate to.

Our backend checks if the user is authenticated

var auth = await


Request.HttpContext.AuthenticateAsync(scheme);

If he is not, we start a challenge, redirecting the user to the social


media’s authentication page. Xamarin Essentials handles this
redirection on the client side for us.

await Request.HttpContext.ChallengeAsync(scheme);

Note: Once the challenge succeeds we are returned an access


token. This token is not used to authenticate to our API. It is from
the social media and we will use it later to get more user
information.

Then, once the user authenticates, we get his information using


appropriate claims.

var claims = auth.Principal.Identities.FirstOrDefault()?.Claims;

var email = string.Empty;

email = claims?.FirstOrDefault(c => c.Type ==


System.Security.Claims.ClaimTypes.Email)?.Value;

var givenName = claims?.FirstOrDefault(c => c.Type

4 of 10 11/28/2020, 4:08 PM
JWT Social auth with ASP.net core and Xamarin Essentials - Cool Coders about:reader?url=https://doumer.me/jwt-social-auth-with-asp-net-core...

== System.Security.Claims.ClaimTypes.GivenName)?.Value;

var surName = claims?.FirstOrDefault(c => c.Type ==


System.Security.Claims.ClaimTypes.Surname)?.Value;

var nameIdentifier = claims?.FirstOrDefault(c =>


c.Type ==
System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;

We then URL encode this user information and redirect. Xamarin


Essentials will get the redirect URL and decode it to use in our app.

1 // Get parameters to send back to the callback

2 var qs = new Dictionary<string, string>

3 {

4 { "access_token", authToken.token },

5 { "refresh_token", string.Empty },

6 { "jwt_token_expires",

7 authToken.expirySeconds.ToString() },

8 { "email", email },

{ "firstName", givenName },
9

10 { "picture", picture },

{ "secondName", surName },
11
};
12

13 // Build the result url

var url = Callback + "://#" + string.Join(


14

15 "&",

qs.Where(kvp =>
16
!string.IsNullOrEmpty(kvp.Value) && kvp.Value != "-1")
17
.Select(kvp =>
18
$"{WebUtility.UrlEncode(kvp.Key)}=
19 {WebUtility.UrlEncode(kvp.Value)}"));

20 // Redirect to final url

Request.HttpContext.Response.Redirect(url);

Note that, the call back scheme above represents a scheme we will
define in our mobile app we will name it: “xamarinapp”

Getting the User’s Picture

You might have noticed that the user’s picture is not passed to our

5 of 10 11/28/2020, 4:08 PM
JWT Social auth with ASP.net core and Xamarin Essentials - Cool Coders about:reader?url=https://doumer.me/jwt-social-auth-with-asp-net-core...

backend even after authentication. We can get this with the access
token returned from the social media, which we mentioned earlier,
or add appropriate claims when setting up authentication.

For Google, we will just add a little bit of configuration while setting
up the Authentication in our startup.cs

google.Scope.Add("profile");

google.Events.OnCreatingTicket = (context) =>

var picture =
context.User.GetProperty("picture").GetString();

context.Identity.AddClaim(new Claim("picture",
picture));

return Task.CompletedTask;

};

For Facebook, we will use the access token to request the user’s
profil picture. Here is how we do that.

Adding JWT Auth

Now that we have our backend setup with social authentication, we


need to handle the creation of tokens and managing users with
ASPnet core identity. This is done easily. We will use mongodb as
our database. But you could use sql server. The process is
basically the same.

For this, we use this nugget package: AspNetCore.Identity.Mongo

Then, we configure Aspnet core identity as follows:

services.AddIdentityMongoDbProvider<AppUser, MongoRole>
(identityOptions =>

....

},

mongoIdentityOptions => {

mongoIdentityOptions.ConnectionString =
Configuration["IdentityDB"];

}).AddDefaultTokenProviders();

When a user authenticates, we want to create the user in our


database or get this user if he already exists. Here is how we do it.

6 of 10 11/28/2020, 4:08 PM
JWT Social auth with ASP.net core and Xamarin Essentials - Cool Coders about:reader?url=https://doumer.me/jwt-social-auth-with-asp-net-core...

private async Task CreateOrGetUser(AppUser appUser)

var user = await


_userManager.FindByEmailAsync(appUser.Email);

if (user == null)

//Create a username unique

appUser.UserName = CreateUniqueUserName($"
{appUser.FirstName} {appUser.SecondName}");

var result = await


_userManager.CreateAsync(appUser);

user = appUser;

await _signInManager.SignInAsync(user, true);

When the user completes social authentication, we then create a


JWT token for this user, with appropriate claims. This token will be
used for authentication. Here is how we do it.

1 private (string token, double expirySeconds) GenerateJwtToken(AppUser user

2 {

3 var issuedAt = DateTimeOffset.UtcNow;

4 var claims = new List<Claim>

5 {

6 new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()), //Subject, should

7 be unique in this scope

8 new Claim(JwtRegisteredClaimNames.Iat, //Issued at, when the token is issued

issuedAt.ToUnixTimeMilliseconds().ToString(), ClaimValueTypes.Integer64
9

10 new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), //Unique


identifier for this specific token
11
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
12
new Claim(ClaimTypes.Email, user.Email)
13
};
14
var key = new
15
SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtKey"]));
16

7 of 10 11/28/2020, 4:08 PM
JWT Social auth with ASP.net core and Xamarin Essentials - Cool Coders about:reader?url=https://doumer.me/jwt-social-auth-with-asp-net-core...

17 var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256)

18 var expires = issuedAt.AddMinutes(Convert.ToDouble(_configuration["JwtExpire"

19 var expirySeconds =
(long)TimeSpan.FromSeconds(Convert.ToDouble(_configuration["JwtExpire"])).TotalSecon
20

21 var token = new JwtSecurityToken(

_configuration["JwtIssuer"],
22

23 _configuration["JwtIssuer"],

24 claims,

25 expires: expires.DateTime,

26 signingCredentials: creds

);
27
return (new JwtSecurityTokenHandler().WriteToken(token), expirySeconds)
28

29 }

30

31

32

Setting up Social Auth in the Mobile app

To setup JWT social auth with asp.net core and xamarin Essentials,
we will have to create a Xamarin Forms project and add Xamarin
Essentials. Then follow these steps.

We configure the callback scheme on iOS in the infor.plist file :

JWT social auth with asp.net core and xamarin Essentials.URL


Scheme iOS

Then on Android we create a web authenticator activity with an


Action View intent.

We add a data scheme to this activity. This activity will be used


during the authentication process by Xamarin Essentials.

8 of 10 11/28/2020, 4:08 PM
JWT Social auth with ASP.net core and Xamarin Essentials - Cool Coders about:reader?url=https://doumer.me/jwt-social-auth-with-asp-net-core...

[Activity(NoHistory = true, LaunchMode =


LaunchMode.SingleTop)]

[IntentFilter(new[] { Intent.ActionView }, Categories = new[] {


Intent.CategoryDefault, Intent.CategoryBrowsable },
DataScheme = "xamarinapp")]

public class WebAuthenticationCallbackActivity :


Xamarin.Essentials.WebAuthenticatorCallbackActivity

Note: The callback scheme should be the same as that on the


backend. The value you chose for its name is case sensitive, as
mentioned in the documentation.

Now that we have configured the platform projects, let’s get into the
shared project. Here, we will invoke the web authenticator API, and
let it do the job of handling redirects, calling web browser e.t.c.

First, in our view model, we have two commands. One for each
button, Signin with Facebook and Google.

GoogleAuthCommand = new Command(async () =>


await OnAuthenticate("Google"));

FacebookAuthCommand = new Command(async () =>


await OnAuthenticate("Facebook"));

Next, when we need to authenticate to our backend, we just call the


web authenticator API, passing in the authentication URL and the
callback scheme. Then that’s all.

var authUrl = new Uri(AuthenticationUrl + scheme);

var callbackUrl = new Uri("xamarinapp://");

var result = await


WebAuthenticator.AuthenticateAsync(authUrl, callbackUrl);

When authentication succeeds, we can get the user’s information in


the result returned.

string authToken = result.AccessToken;

string refreshToken = result.RefreshToken;

var jwtTokenExpiresIn =
result.Properties["jwt_token_expires"];

Then using Shell navigation, we URL encode the user info and

9 of 10 11/28/2020, 4:08 PM
JWT Social auth with ASP.net core and Xamarin Essentials - Cool Coders about:reader?url=https://doumer.me/jwt-social-auth-with-asp-net-core...

pass it to the User profile view model as follows.

var userInfo = new Dictionary<string, string>

{ "token", authToken },

{ "name", $"{result.Properties["firstName"]}
{result.Properties["secondName"]}"},

{ "picture",
HttpUtility.UrlDecode(result.Properties["picture"]) }

};

var url = "UserProfil" + '?' + string.Join("&",


userInfo.Select(kvp => $"{WebUtility.UrlEncode(kvp.Key)}=
{WebUtility.UrlEncode(kvp.Value)}"));

await AppShell.Current.GoToAsync(url);

If the user cancels the authentication process, or closes the


browser before it completes, a “TaskCanceledException” will be
thrown, and we need to handle it.

Conclusion

With just a few lines of code, we made JWT social auth with
ASP.net core and Xamarin Essentials functionality in our mobile
app. There Microsoft’s MSAL library for more advanced
authentication scenarios. But for small size mobile applications, this
approach is good enough. Especially if you are willing to prototype
quickly.

References

https://devblogs.microsoft.com/xamarin/authentication-xamarin-
essentials-aspnet/?WT.mc_id=DT-MVP-5003277

https://developer.android.com/reference/android/content
/IntentFilter#addDataSchemeSpecificPart(java.lang.String,%20int)

Follow me on social media and stay updated

10 of 10 11/28/2020, 4:08 PM

You might also like