{"id":217,"date":"2022-01-07T11:10:32","date_gmt":"2022-01-07T11:10:32","guid":{"rendered":"https:\/\/blog.citrus-lime.com\/crmc\/?p=217"},"modified":"2022-01-07T11:10:33","modified_gmt":"2022-01-07T11:10:33","slug":"part-5-power-apps-portals-how-to-connect-azure-b2c-with-linked-in","status":"publish","type":"post","link":"https:\/\/blog.citrus-lime.com\/crmc\/part-5-power-apps-portals-how-to-connect-azure-b2c-with-linked-in\/","title":{"rendered":"Part 5 &#8211; Power Apps Portals: How To Connect Azure B2C With Linked-In"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/th.bing.com\/th\/id\/R6e154f80072e0f134105ec35599d74a6?rik=UvWo5zE1ezAHlg&amp;riu=http%3a%2f%2fpngimg.com%2fuploads%2flinkedIn%2flinkedIn_PNG24.png&amp;ehk=veq8XBJMI1epEE3nPbaJnSO9W0JTzrhwNTFwUom87w8%3d&amp;risl=&amp;pid=ImgRaw\" alt=\"See the source image\" width=\"247\" height=\"247\" \/><\/figure><\/div>\n\n\n\n<p>Once our Portal Apps Portal is connected to Azure B2C, we can use our B2C Tenant as the middle-man to allow our Users to log in via their existing credentials with a number of other general Apps or Services.<\/p>\n\n\n\n<p>This can be particularly useful to allow Users to log into our Portal using their existing Facebook, Twitter or LinkedIn Accounts.<\/p>\n\n\n\n<p>This article will focus on how we can connect LinkedIn to our Portal and let our end users log in via their LinkedIn Account Details.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1 &#8211; LinkedIn Developer \u2013 Create an App<\/h3>\n\n\n\n<p>Our first step is to open Linkedin for Developers and create an App that will link our Azure B2C with Linkedin \u2013 this can be started here:&nbsp;<a href=\"https:\/\/www.linkedin.com\/developers\/\">Developers | Linkedin<\/a><\/p>\n\n\n\n<p>From there we can create a New App with the following details:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>App Name<\/li><li>Linkedin Page to declare your Company or App in Linkedin<\/li><li>Privacy Policy is preferred to declare how your App will use the Data from any Linkedin User Accounts that link with your App \u2013 this is not required and so can be avoided whilst in Development and Testing, but should be detailed as a requirement for any Production Portal given the Handshake between your Application and data from LinkedIn.<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_5AEC0D8B.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_6F715D09.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<p><br>With our App declared with Linkedin \u2013 this will give us a Client ID and Secret that we will use to configure into Azure B2C<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_6132E419.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_2ECF109A.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<p><br>We also need to navigate into Products and add the \u2018Sign In with Linkedin\u2019 feature to our App:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_115CBF8E.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_031E469E.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<p>We then take this into Azure B2C.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><br>Step 2 &#8211; Azure B2C Identity Provider<\/h3>\n\n\n\n<p>We start this second step by navigating into Identity Providers.<\/p>\n\n\n\n<p>This will present a standard list of Social OpenID Providers, including LinkedIn.<\/p>\n\n\n\n<p>We can then enable the LinkedIn Provider to configure the connection between our B2C Tenant and LinkedIn \u2013 here we supply the Client ID and Secret that LinkedIn has generated for our App.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_65ABF591.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_1A4C51CD.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;<br><br>Once configured in our Azure B2C, this will then give us a Callback URL that we will add into the configuration of our App back in LinkedIn Developer \u2013 this is typically:&nbsp;<a href=\"https:\/\/[tenant-name].b2clogin.com\/%5btenant-name%5d.onmicrosoft.com\/oauth2\/authresp\">https:\/\/[tenant-name].b2clogin.com\/[tenant-name].onmicrosoft.com\/oauth2\/authresp<\/a><\/p>\n\n\n\n<p>We also need to create a second Callback URL in the LinkedIn Developer App, this should be in the format:&nbsp;<a href=\"https:\/\/[tenant-name].b2clogin.com\/%5bdirectory-tenant-id%5d\/oauth2\/authresp\">https:\/\/[tenant-name].b2clogin.com\/[directory-tenant-id]\/oauth2\/authresp<\/a>&nbsp;where the directory-tenant-id is taken from our Azure B2C app overview page under essentials, it is the value for \u2018Directory (tenant) ID\u2019 here.<\/p>\n\n\n\n<p><strong>N.B. these two callback URLs are case sensitive, and they must be entirely in lower case to work, so make sure you convert both URLS to all lower case!\u201d<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_27B264D3.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_47613E9B.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><br><br><br>Step 3 \u2013 See it in action!!<\/h3>\n\n\n\n<p>With this in place and our Sign in with LinkedIn Product approved in the App \u2013 we can test the way Users can log in or create an Account with our Portal.<\/p>\n\n\n\n<p>If we navigate into our Portal and attempt to log in via B2C, we will see the usual B2C Login but with an additional option to use Linkedin:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_29EEED8F.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_1086EA55.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<p><br>We can click on our new LinkedIn option to log in with our existing LinkedIn Account rather than be forced to create a wholly new password just for Azure B2C.<\/p>\n\n\n\n<p>When using our LinkedIn Account with our Portal for the first time, we do still need to register ourselves to Azure B2C and specify the same key details we have configured in our Azure B2C.&nbsp; In our example here: First Name, Last Name and Job Title \u2013 as we set up in one of the articles earlier in this series.<\/p>\n\n\n\n<p>As the authentication passes through Azure B2C to then federate with LinkedIn \u2013 the Contact tracking works in exactly the same way as non-federated B2C:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Contacts match \/ deduplicate on Email Address in the same way<\/li><li>Each Contact will track the External Identity between Dynamics \/ Power Apps and Azure B2C<\/li><li>No Password is stored in Dynamics<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li><\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_101AB760.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_72A86653.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<p><br><br>This means that (as we would expect with Power Apps Portals) the same Contact Record is captured for each User with the details we need for each Portal User \u2013 with the Authentication Provider going via Azure B2C\u2019s connection with LinkedIn so we never need to store a Password in Azure B2C.<\/p>\n\n\n\n<p>Whilst the Contact in Dynamics is exactly the same regardless of the end Identity Provider \u2013 we can see this detail in Azure B2C as the broker between validated identities elsewhere and our consumer in Power Apps Portals.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_795B6FD6.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_522126A1.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<p><br><br>As a general security note, any system where we can avoid storing and particularly viewing a Password is inherently more secure than the alterative \u2013 there is a risk where we are outsourcing that authentication to a 3rd party supplier and so are only as secure as that 3rd party\u2019s security itself; but in general Microsoft\u2019s method of handling Azure B2C and LinkedIn\u2019s security will be stronger than any Custom Model we may implement for a specific Portal. (with a possible side note that established Authentication Providers may be a larger target than a smaller \u2018homebrew\u2019 system \u2013 but in general, leveraging the experience and investment of establishment providers is a stronger security approach.)<\/p>\n\n\n\n<p>This approach of taking the power of the network and interconnected networks working together in the Cloud is in itself a good example of how the Cloud improves over an older approach of dedicated systems or sharing common code modules that are still installed independently on-premise.<\/p>\n\n\n\n<p>This connection of the LinkedIn Account to Azure B2C also ensures that MFA is enforced to validate identities connecting to the Linked identity.<\/p>\n\n\n\n<p>Once done, our end result is that a User can log into our Portal through their LinkedIn Username and Password \u2013 meaning that our Portal Audience has one less password to remember.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_58D43024.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_3B61DF18.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<p><br><br>Whilst simply removing the need for our User\u2019s to have a unique Password may seem like a small improvement \u2013 it lowers the barrier to entry or friction for Users adopting our Portal.<\/p>\n\n\n\n<p>This ease of use means that more Users will engage with our Portal, and so allow any Portal Rollout to be more successful.<\/p>\n\n\n\n<p>This concept of getting the foundation right can often be crucial to getting better ROI out of any project or technology deployment.<\/p>\n\n\n\n<p><br>Step 4 \u2013 Direct Connection from Power Apps Portals to LinkedIn<\/p>\n\n\n\n<p>This series of articles is focused on how we can use Azure B2C to connect our Portal to a number of different identity providers for a better and more secure Portal.<\/p>\n\n\n\n<p>But it is worth noting that Power Apps Portals can be connected directly into LinkedIn without going via B2C.<\/p>\n\n\n\n<p>This is available via a new set of functionality from the recent end of 2020 Release Wave of functionality in Power Apps Portals and can be seen from the Power Apps Maker area:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_4214E89B.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_1ADA9F66.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<p>Clicking into Authentication Providers then presents us with a similar list to Azure B2C but with a crucial difference that this is connecting directly from the Portal to LinkedIn<\/p>\n\n\n\n<p>For LinkedIn this requires many of the same details for a Client ID and Secret from our LinkedIn App, and adding the link to allow LinkedIn to passback into your Portal.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_367F2B5C.png\"><img decoding=\"async\" src=\"https:\/\/license.citruslime.com\/cs\/blogs\/crmcs\/image_thumb_041B57DD.png\" alt=\"image\" title=\"image\" \/><\/a><\/figure>\n\n\n\n<p><br><br>There is then advantages and disadvantages to direct authentication vs going through a centralised broker such as your B2C Tenant \u2013 with our preference coming down on the side of B2C.<\/p>\n\n\n\n<p>To avoid this article becoming even longer, this will be the subject of a follow-up article looking specifically at this direct route for Portals and LinkedIn.<br><\/p>\n\n\n\n<p><strong>We hope you found our 5 Part Power Apps Portals Guide helpful \u2013 If you have any questions for&nbsp;<\/strong><a href=\"https:\/\/www.crmcs.co.uk\/\"><strong>CRMCS<\/strong><\/a><strong>, please don\u2019t hesitate to contact us at&nbsp;<\/strong><a href=\"mailto:contact@crmcs.co.uk\"><strong>contact@crmcs.co.uk<\/strong><\/a><br><\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<p>Fur<strong>ther Reading\u2026<\/strong><\/p>\n\n\n\n<p>We understand there are a wealth of articles on Azure B2C \u2013 but not too many on integrating with a specific provider such as LinkedIn and seeing this in action with Power Apps Portals, and was one of the reasons for focusing on LinkedIn as a single provider to document how we action these steps.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Once our Portal Apps Portal is connected to Azure B2C, we can use our B2C Tenant as the middle-man to allow our Users to log in via their existing credentials with a number of other general Apps or Services. This can be particularly useful to allow Users to log into our Portal using their existing<\/p>\n","protected":false},"author":43,"featured_media":43,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_tribe_ticket_capacity":"0","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[3],"tags":[],"class_list":{"0":"post-217","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-crm"},"featured_image_src":"https:\/\/blog.citrus-lime.com\/crmc\/wp-content\/uploads\/sites\/30\/2021\/11\/Untitled-design-41.png","author_info":{"display_name":"jadesmith","author_link":"https:\/\/blog.citrus-lime.com\/crmc\/author\/jadesmith\/"},"_links":{"self":[{"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/posts\/217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/users\/43"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/comments?post=217"}],"version-history":[{"count":1,"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/posts\/217\/revisions"}],"predecessor-version":[{"id":218,"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/posts\/217\/revisions\/218"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/media\/43"}],"wp:attachment":[{"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/media?parent=217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/categories?post=217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.citrus-lime.com\/crmc\/wp-json\/wp\/v2\/tags?post=217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}