{"id":39164,"date":"2019-06-26T14:45:04","date_gmt":"2019-06-26T19:45:04","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/appcenter\/?p=39164"},"modified":"2019-06-27T12:44:52","modified_gmt":"2019-06-27T17:44:52","slug":"json-web-token-and-react-native-support-arrives-to-visual-studio-app-center-auth","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/appcenter\/json-web-token-and-react-native-support-arrives-to-visual-studio-app-center-auth\/","title":{"rendered":"JSON Web Token and React Native Support Arrives to Visual Studio App Center Auth"},"content":{"rendered":"<p>We shipped <a href=\"https:\/\/devblogs.microsoft.com\/appcenter\/introducing-visual-studio-app-center-auth\/\">App Center Auth<\/a> in early preview on May 7, and it\u2019s been an exciting month and a half since our launch! During this time we\u2019ve actively engaged with our developers and rolled out a couple of product improvements based on your feedback.<\/p>\n<p>App Center Auth empowers app developers to have a simple user experience for an identity management solution that relies on the robust enterprise capabilities of Azure Active Directory B2C (Azure AD B2C). We simplified the in-app Azure AD B2C configuration through App Center\u2019s SDK by wrapping around <a href=\"https:\/\/docs.microsoft.com\/azure\/active-directory\/develop\/reference-v2-libraries\">Microsoft Authentication Library (MSAL)<\/a>. By integrating a couple of lines of code, you\u2019ll be able to connect an existing Azure AD B2C tenant and use the signed in user\u2019s identity to view their data and send push notifications to the user.<\/p>\n<h4>Exposing the JSON Web Tokens (JWTs)<\/h4>\n<p>You gave great feedback about <a href=\"https:\/\/github.com\/microsoft\/appcenter\/issues\/393\">exposing the JWT<\/a> so we immediately set out to add this feature in the June release of the App Center Auth SDK for <a href=\"https:\/\/github.com\/Microsoft\/AppCenter-SDK-Apple\">iOS<\/a>, <a href=\"https:\/\/github.com\/microsoft\/appcenter-sdk-android\">Android<\/a>, <a href=\"https:\/\/github.com\/microsoft\/appcenter-sdk-dotnet\">Xamarin<\/a> and <a href=\"https:\/\/www.npmjs.com\/package\/appcenter-auth\">React Native<\/a>.<\/p>\n<h3>Getting the Access and Id Token<\/h3>\n<p>App Center Auth SDK now exposes the two <a href=\"https:\/\/jwt.io\/\">JSON Web Tokens<\/a> in the Auth signIn() method: the <a href=\"https:\/\/docs.microsoft.com\/azure\/active-directory-b2c\/active-directory-b2c-reference-tokens#token-types\">access and ID token<\/a>. You can parse this token to obtain user profile information that you\u2019ve collected during the sign-in process or use the token to secure an Azure Function App based on the signed-in user\u2019s authorization.<\/p>\n<p>When a user signs-in to your app, you can specify in Azure AD B2C the user profile fields to collect so that they will be available in the tokens. The key benefit of collecting the user profile information such as `display name` is to interact with the signed in user in the display UI. For example, developers can display \u201cWelcome, Lupita!\u201d to better engage and personalize your sign-in confirmation page.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-39165 size-large\" src=\"https:\/\/devblogs.microsoft.com\/appcenter\/wp-content\/uploads\/sites\/3\/2019\/06\/word-image-3-1024x557.png\" alt=\"\" width=\"640\" height=\"348\" srcset=\"https:\/\/devblogs.microsoft.com\/appcenter\/wp-content\/uploads\/sites\/3\/2019\/06\/word-image-3-1024x557.png 1024w, https:\/\/devblogs.microsoft.com\/appcenter\/wp-content\/uploads\/sites\/3\/2019\/06\/word-image-3-300x163.png 300w, https:\/\/devblogs.microsoft.com\/appcenter\/wp-content\/uploads\/sites\/3\/2019\/06\/word-image-3-768x418.png 768w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/p>\n<p style=\"text-align: center;\"><em>Figure\u00a01\u00a0\u2013 Application claims in Azure AD B2C\u00a0<\/em><\/p>\n<p>The ID token will contain the user profile attributes that you\u2019ve selected to collect in the Azure AD B2C tenant and is used by your application. The app can decode the token\u2019s contents to get user information such as display name, email and so on, to customize the user experience in the display UI.<\/p>\n<p>The access token is a credential that is used by your application to access APIs and resource servers, and is used by an API. The access token informs the API that the bearer of the token has the right permissions to access the API. This API can then be used to perform actions (determined by the user\u2019s permissions) such as read, write and so on. When the API receives this access token, it must first validate the signature and a few claims to prove that the token is valid.<\/p>\n<p>Here is a code snippet on how you can access the tokens from the signIn() method in C#:<\/p>\n<pre class=\"lang:default decode:true\">async Task SignInAsync()\r\n{\r\n    try\r\n    { \r\n        \/\/ Sign-in succeeded, UserInformation is not null.\r\n        UserInformation userInfo = await Auth.SignInAsync();\r\n\r\n        \/\/ Get tokens. They are not null.\r\n\r\n        string idToken = userInfo.IdToken;\r\n        string accessToken = userInfo.AccessToken;\r\n\r\n        \/\/ Do work with either token.\r\n    } \r\n    catch (Exception e)\r\n    {\r\n        \/\/ Do something with sign-in failure.\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>Learn more about retrieving the access and ID token for your <a href=\"https:\/\/docs.microsoft.com\/appcenter\/sdk\/auth\/ios#get-access-token-and-id-token\">iOS<\/a>, <a href=\"https:\/\/docs.microsoft.com\/appcenter\/sdk\/auth\/android#get-access-token-and-id-token\">Android<\/a>, <a href=\"https:\/\/docs.microsoft.com\/appcenter\/sdk\/auth\/xamarin#get-access-token-and-id-token\">Xamarin<\/a> and <a href=\"https:\/\/docs.microsoft.com\/appcenter\/sdk\/auth\/react-native#get-access-token-and-id-token\">React Native<\/a> apps.<\/p>\n<h3>Decoding the Tokens<\/h3>\n<p>To make sense of the contents of the token, you must decode it. You can decode user profile information such as the display name or the email address from the ID token or the access token.<\/p>\n<p>Before decoding the token to get user profile information, the Azure AD B2C tenant must be configured to include the user profile fields in the tokens. Learn more about decoding the access and ID token for your <a href=\"https:\/\/docs.microsoft.com\/appcenter\/sdk\/auth\/ios#decoding-tokens\">iOS<\/a>, <a href=\"https:\/\/docs.microsoft.com\/appcenter\/sdk\/auth\/android#decoding-tokens\">Android<\/a>, <a href=\"https:\/\/docs.microsoft.com\/appcenter\/sdk\/auth\/xamarin#decoding-tokens\">Xamarin<\/a> and <a href=\"https:\/\/docs.microsoft.com\/appcenter\/sdk\/auth\/react-native#decoding-tokens\">React Native<\/a> apps.<\/p>\n<p>Here is a code snippet on how you can decode the user profile information for <strong>Display Name<\/strong> and <strong>Email Addresses<\/strong> in the tokens in C#:<\/p>\n<pre class=\"lang:default decode:true\">using System.Linq; \r\nusing System.IdentityModel.Tokens.Jwt;\r\n\/\/ Decode the raw token string to read the claims.\r\n\r\nvar tokenHandler = new JwtSecurityTokenHandler();\r\ntry\r\n{\r\n    var jwToken = tokenHandler.ReadJwtToken(userInfo.IdToken);\r\n\r\n    \/\/ Get display name.\r\n    var displayName = jwToken.Claims.FirstOrDefault(t =&gt; t.Type == \"name\")?.Value;\r\n\r\n    if (displayName != null)\r\n    {\r\n        \/\/ Do something with display name.\r\n    }\r\n\r\n    \/\/ Get first email address.\r\n    var firstEmail = jwToken.Claims.FirstOrDefault(t =&gt; t.Type == \"emails\")?.Value;\r\n    if (firstEmail != null)\r\n    {\r\n        \/\/ Do something with email.\r\n    }\r\n} \r\ncatch (ArgumentException)\r\n{\r\n    \/\/ Handle error.\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>You can also paste your token in <a href=\"http:\/\/jwt.ms\/\">http:\/\/jwt.ms\/<\/a> to decode it.<\/p>\n<h3>Checking if the User is Signed In<\/h3>\n<p>To check if the user is signed in, you can call the signIn() method again. The SDK will not show the sign-in UI again, unless the saved sign-in information has expired or has been revoked by the authentication server.<\/p>\n<p>Alternatively, you can also save the result of the signIn() method when it is invoked the first time in a boolean variable. In the example in C# below, if the signIn() method returns a null `account_id`, meaning that the user did not sign in successfully, then we assign a boolean variable `SignInOut` as `false`.<\/p>\n<pre class=\"lang:default decode:true \">async Task ExecuteSignIn()\r\n{\r\n    if (SignInOut.IsSignedIn)\r\n    {\r\n\u00a0\u00a0\u00a0\u00a0    Auth.SignOut();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SignInOut.IsSignedIn = false;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Do something\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return;\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0try\r\n\u00a0\u00a0\u00a0\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Sign-in succeeded, UserInformation is not null.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var result =\u00a0\u00a0await Auth.SignInAsync();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0string accessToken = result.AccessToken;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Decode the raw token string to read the claims.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var tokenHandler = new JwtSecurityTokenHandler();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    var jwToken = tokenHandler.ReadJwtToken(userInfo.IdToken);\r\n            \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Get display name.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var displayName = jwToken.Claims.FirstOrDefault(t =&gt; t.Type == \"name\")?.Value;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (displayName != null)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    \/\/ Do something with display name.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n            \r\n            \/\/ Get first email address.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var firstEmail = jwToken.Claims.FirstOrDefault(t =&gt; t.Type == \"emails\")?.Value;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (firstEmail != null)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Do something with email.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0catch (ArgumentException)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    \/\/ Handle error.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\r\n        Analytics.TrackEvent(\"signin id\", new System.Collections.Generic.Dictionary&lt;string, string&gt;(){ { \"AccountId\", result.AccountId } });\r\n\u00a0\u00a0\u00a0\u00a0    SignInOut.IsSignedIn = true;\r\n\u00a0\u00a0\u00a0\u00a0} \r\n\u00a0\u00a0\u00a0\u00a0catch (System.Exception e)\r\n\u00a0\u00a0\u00a0\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0    \/\/ Handle error.\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0OnPropertyChanged(\"SignInOut\");\r\n\u00a0\u00a0\u00a0\u00a0\/\/ Do something\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h4>Auth Support for React Native<\/h4>\n<p>During <a href=\"https:\/\/www.youtube.com\/watch?v=k3G0XoY8XII\">our session at Microsoft Build<\/a> in May, we mentioned that we would support additional platforms for Auth in our roadmap. We\u2019re excited to announce that support for React Native is finally here! App developers can now configure Auth for <a href=\"https:\/\/docs.microsoft.com\/appcenter\/sdk\/auth\/react-native\">React Native<\/a> apps.<\/p>\n<p>For more details on our latest changes view the <a href=\"https:\/\/github.com\/microsoft\/appcenter\/issues\/474\">full list of the user experience improvements<\/a> that we rolled out.<\/p>\n<h4>Collaborative Feedback<\/h4>\n<p><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">App Center Auth is in early preview<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">\u00a0and\u00a0<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">over the coming months, we invite you to<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">\u00a0<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">collaborate with\u00a0<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">us in our journey\u00a0<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">where your feedback will help<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">\u00a0<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">us\u00a0<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">build an\u00a0<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun CommentStart SCXW256829659 BCX0\">identity management<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">\u00a0solution that you will love<\/span><\/span><span class=\"TextRun SCXW256829659 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW256829659 BCX0\">.\u00a0<\/span><\/span>Get started with <a href=\"https:\/\/docs.microsoft.com\/en-us\/appcenter\/auth\/\">App Center Auth<\/a>, and comment on what you\u2019d like to see in our <a href=\"https:\/\/github.com\/Microsoft\/appcenter\">GitHub repo<\/a> here.<\/p>\n<p>Have fun, and happy hacking! \u26a1<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We shipped App Center Auth in early preview on May 7, and it\u2019s been an exciting month and a half since our launch! During this time we\u2019ve actively engaged with our developers and rolled out a couple of product improvements based on your feedback.<\/p>\n","protected":false},"author":660,"featured_media":39165,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[16],"tags":[],"class_list":["post-39164","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-mobiledev"],"acf":[],"blog_post_summary":"<p>We shipped App Center Auth in early preview on May 7, and it\u2019s been an exciting month and a half since our launch! During this time we\u2019ve actively engaged with our developers and rolled out a couple of product improvements based on your feedback.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/posts\/39164","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/users\/660"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/comments?post=39164"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/posts\/39164\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/media\/39165"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/media?parent=39164"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/categories?post=39164"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/tags?post=39164"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}