<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Detroit Dave</title>
    <description>Old Man Yells at Cloud and Young Programmers</description>
    <link>https://www.detroitdave.dev/</link>
    <atom:link href="https://www.detroitdave.dev/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 22 Mar 2023 15:01:54 +0000</pubDate>
    <lastBuildDate>Wed, 22 Mar 2023 15:01:54 +0000</lastBuildDate>
    <generator>Jekyll v4.0.0</generator>
    
      <item>
        <title>Reason #1,287,529 WSL Still Vexes Me</title>
        <description>&lt;p&gt;WSL is sometimes a very useful tool for working in a Linux environment. It is super useful because it is light weight and integrated in Windows. The drawback to using WSL is from time to time you run across some inconsistencies that are endlessly frustrating before you can “bottom out” the problem. Once figuring it out, it is of course evident where the problem came from but just makes you shake your head and remind you that doing anything cross-platform in WSL is “mostly” cross platform but not always. So, what did I discover and how did we fix it.&lt;/p&gt;

&lt;p&gt;My task was to put together a bash shell script that used the &lt;a href=&quot;https://learn.microsoft.com/en-us/cli/azure/&quot;&gt;Azure CLI&lt;/a&gt; to work with &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/azure-resource-manager/managed-applications/overview&quot;&gt;Azure Managed Applications&lt;/a&gt;. To create some of the variables needed for the bash script we set up some variables that were &lt;strong&gt;az cli&lt;/strong&gt; commands getting a single piece of data. Now please remember, I am by no means a Bash expert and know simply enough to be dangerous or at the very least get myself in trouble. Let’s take a look at WSL and the commands used to set up the variables&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/2023-03-21/wsl-vex-1.png&quot; alt=&quot;Image 1 - The problem&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can see that that I ran the data collection part of the script on the first line. It simply returns a string that is the subscription id and puts in the variable called appid (line 1). Next, I build a second variable called &lt;em&gt;managedGroupId&lt;/em&gt; using that first variable essentially inserting it into the string represented there (line 3). You can see the results of echoing the variable &lt;em&gt;managedGroupId&lt;/em&gt;. What in the Sam Hill is that output!?!?!? I kept thinking &lt;em&gt;“well maybe because the command result is async”&lt;/em&gt;, &lt;em&gt;“maybe it is over writing the buffer on timing”&lt;/em&gt;, etc….. As I said, I am no Bash expert so I was perplexed thinking there was some Bash assumptions that I was overlooking. It took me roughly 4 hours to figure out the problem. The problem was derived from one Stackoverflow thread (&lt;a href=&quot;https://unix.stackexchange.com/questions/698240/environment-variable-with-command-substitution-isnt-getting-set-correctly&quot;&gt;here&lt;/a&gt; for proper attribution). The problem is that since you are using WSL it appears that the windows command’s output (even though this is WSL) has a trailing &lt;CR&gt; (\r, 0x0D, ^M) character that makes the line fold back and continue at pos 1.&lt;/CR&gt;&lt;/p&gt;

&lt;p&gt;The way to fix the Bash script to overcome the WSL problem (and not torch your script when you run on Linux) is to pipe it into another command to remove the trailing &lt;CR&gt; like so:&lt;/CR&gt;&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tr -d $'\\r'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This produces the desired output like so:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/2023-03-21/wsl-vex-2.png&quot; alt=&quot;Image 2 - The Solution&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I hope this shows up on the internet and saves some time for everyone! 😊&lt;/p&gt;
</description>
        <pubDate>Tue, 21 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://www.detroitdave.devhttps://www.detroitdave.dev/2023/03/wsl-still-vexes-me.html</link>
        <guid isPermaLink="true">https://www.detroitdave.devhttps://www.detroitdave.dev/2023/03/wsl-still-vexes-me.html</guid>
        
        <category>Azure</category>
        
        <category>Bash</category>
        
        <category>WSL</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Azure Devops Tidbits</title>
        <description>&lt;p&gt;I was recently working on a project that invovled doing a lot of work inside &lt;a href=&quot;https://azure.microsoft.com/en-us/solutions/devops/&quot;&gt;Azure DevOps&lt;/a&gt; (AzDO). We had some unique challenges to solve and I continually ran into trouble looking for ways to treat the AzDO Git repository as I would if I were going to download files from a Git repository (using the raw endpoints). Since I struggled finding a solution, and was only able to solve with a steer from a collegue, I thought I would publish an article so others could find.&lt;/p&gt;

&lt;h2 id=&quot;azdo-git-and-curl&quot;&gt;AzDO Git and curl&lt;/h2&gt;

&lt;p&gt;This was the one that had me spinning for a while. If you take a look at the docs for the &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/devops/integrate/how-to/call-rest-api?view=azure-devops#versions&quot;&gt;REST endpoints&lt;/a&gt; you would think you could grab the curl example and rock and roll. My experimenting proved that to be wrong. Take a look at the example below:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;curl -u {username}[:{personalaccesstoken}] https://dev.azure.com/{organization}/_apis/projects?api-version=2.0&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, how do I use this? Are the ‘{}’ supposed to stay? Are they supposed to go? What about the ‘[]’? The only thing I found that worked for this was simply to use:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;username:pat&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once this was done. I could get into most of the REST API end points.&lt;/p&gt;

&lt;h2 id=&quot;single-file-downloads&quot;&gt;Single File downloads&lt;/h2&gt;

&lt;p&gt;This one was a bit more interesting. The first thing you have to try to suss out is where is the endpoint to use. This was not as simple. With a steer from a collegue I found it here (replace all caps with your information):&lt;/p&gt;

&lt;p&gt;&lt;em&gt;https://dev.azure.com/ORGNAME/PROJECT/_apis/git/repositories/REPOSITORY/items/PATH-TO-FILE?versionType=Branch&amp;amp;versionOptions=None&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Using the same curl -u format as above will get you any file you need form the repository. As an interesting side note, you could also do the curl command like so to the same effect. I have not tested this everywhere and have only used this format to get files (replace all caps with your information):&lt;/p&gt;

&lt;p&gt;&lt;em&gt;curl -o FILE -s https://PAT@dev.azure.com/ORGNAME/PROJECTNAME/_apis/git/repositories/REPOSITORY/items/PATH-TO-FILE?versionType=Branch&amp;amp;versionOptions=None&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;an-interesting-trick-to-execute-code-in-a-pipeline&quot;&gt;An interesting trick to execute code in a pipeline&lt;/h2&gt;

&lt;p&gt;We also found ourselves in a situation where we needed to do something in a build pipeline that was difficult to do in bash while running a build pipeline. This may be simply that I am not a bash God but we foind updating a json file in the build was difficult. Below is the dirty hack we used to get this done. :-)&lt;/p&gt;

&lt;p&gt;We decided to use a little C# script (CSX) to solve our problem. The first thing we need to do was place a CSX file in the repository we were looking at. In this case the script was simply going to update some JSON:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-CS&quot;&gt;#r &quot;nuget: Newtonsoft.Json, 12.0.3&quot;

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

public class Extension
{
    public string name { get; set; }
    public string description { get; set; }
    public string type { get; set; }
    public string version { get; set; }
    public string filePath { get; set; }
}

public class Catalog
{
    public List&amp;lt;Extension&amp;gt; extensions { get; set; }
}

if (Args.Count != 3)
{    
    Console.WriteLine(&quot;Three arguments must be passed in: &amp;lt;index.json&amp;gt; &amp;lt;name&amp;gt; &amp;lt;version&amp;gt;&quot;);
    return -1;
}

Catalog catalog = JsonConvert.DeserializeObject&amp;lt;Catalog&amp;gt;(File.ReadAllText(Args[0]));
var extension = catalog.extensions.FirstOrDefault(x=&amp;gt; x.name.Equals(Args[1]));
extension.version = Args[2];
File.WriteAllText(Args[0], JsonConvert.SerializeObject(catalog, Formatting.Indented));
Console.WriteLine(&quot;Updated&quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once this was in the repository we needed to two more things: 1) get the tool to run the scripts and 2) run it. To install the NET Core SDK tool in your pipeline simply run:&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;_curl -s https://raw.githubusercontent.com/filipw/dotnet-script/master/install/install.sh&lt;/td&gt;
      &lt;td&gt;sudo bash_&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;From there you can simply execute the above script (in this case called ) like so:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;sudo dotnet script ./update-version.csx extensions/index.json “core” $(Build.BuildNumber)&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap Up&lt;/h2&gt;

&lt;p&gt;I had a heck of a time trying to track down how to do this. I hope any of this is helpful to someone or at least finding it is easier.&lt;/p&gt;
</description>
        <pubDate>Sun, 06 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://www.detroitdave.devhttps://www.detroitdave.dev/2020/09/azdo-helper-info.html</link>
        <guid isPermaLink="true">https://www.detroitdave.devhttps://www.detroitdave.dev/2020/09/azdo-helper-info.html</guid>
        
        <category>AzDO</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>A simple example of Azure B2C integration with Flutter</title>
        <description>&lt;h2 id=&quot;the-intro&quot;&gt;The intro&lt;/h2&gt;

&lt;p&gt;I love Azure. I mean, sometimes it is a love/hate thing, but I really &lt;strong&gt;LOVE&lt;/strong&gt; Azure. :smile:&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, I like other cloud platforms as well, but I find it, like most things Microsoft tends to do in the developer space, easy for devs to get into. After years of doing my own authentication systems and integration of others, I was thrilled when Azure Active Directory B2C came out. It was especially great for putting that same user identity and security into many mobile apps I have built. As I have spent time adopting Flutter, it seems the documentation out there on how to integrate and use it more fully is spartan at best and scattered and erratic at worst. I currently have someone who asked to be an intern with me and learn the “craft” of coding, and I found getting them up to speed on this was time consuming. I thought I would document what it takes to stand up a B2C directory and integrate it into a Flutter app from an extremely simplistic perspective. In subsequent articles, I will move up the chain in complexity. You might wonder when you read this, “why is he taking me into one document and then jumping out and to another?”. The reason for this is actually simple. Azure B2C is a wide and varied product. It has a &lt;strong&gt;TON&lt;/strong&gt; of different functionalities. I found it difficult to seperate the “wheat from the shaff” when reading through all these. It was always the “extra” information that threw me off, as I could not figure out what one thing had to do with another. I hope you enjoy the journey, and I hope you find this useful.&lt;/p&gt;

&lt;h2 id=&quot;the-premise&quot;&gt;The premise&lt;/h2&gt;

&lt;p&gt;So what do we want to accomplish? The business desire here is to:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;create a mobile app in Flutter where our users log in via an Azure B2C directory we create&lt;/li&gt;
  &lt;li&gt;access users’ profile information from the mobile application&lt;/li&gt;
  &lt;li&gt;allow users to log out of the app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This in a nutshell is the simplest use case for a mobile app. you might ask youself, “well, what about calling back end APIs and such?”. I wanted to start with the simplest thing— in my experience, trying to wind all of that in at one time was confusing and made troubleshooting harder while learning.&lt;/p&gt;

&lt;h3 id=&quot;what-technology-will-we-be-using&quot;&gt;What technology will we be using?&lt;/h3&gt;

&lt;p&gt;We will be using:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Azure Active Directory B2C - &lt;a href=&quot;https://azure.microsoft.com/en-us/services/active-directory-b2c/&quot;&gt;https://azure.microsoft.com/en-us/services/active-directory-b2c/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Flutter - &lt;a href=&quot;https://flutter.dev/&quot;&gt;https://flutter.dev/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;App Auth - &lt;a href=&quot;https://appauth.io/&quot;&gt;https://appauth.io/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;getting-b2c-up-and-running&quot;&gt;Getting B2C up and running&lt;/h3&gt;

&lt;h4 id=&quot;create-b2c-directory&quot;&gt;Create B2C Directory&lt;/h4&gt;

&lt;p&gt;We start by creating the Azure Active Directory B2C instance. Microsoft has a ton of documentation. I would start &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-tenant&quot;&gt;here&lt;/a&gt; to get the base directory in place. I have named mine &lt;strong&gt;detroitdaveb2c&lt;/strong&gt;.&lt;/p&gt;

&lt;h4 id=&quot;register-the-mobile-application&quot;&gt;Register the Mobile Application&lt;/h4&gt;

&lt;p&gt;The next thing we have to do is create/register an application and create the user flows within this directory. The process to create a web app and create a native app are very different. This was one of the confusing things to get through as there are a ton of options. This &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/active-directory-b2c/signin-appauth-ios?tabs=applications&quot;&gt;article&lt;/a&gt; is a good one to follow to get those steps correct. While creating/registering the application, these tips may be useful:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Pay attention to the redirect URI in your app. You will find different articles with different ways of laying this out. One of the examples used is &lt;em&gt;com.onmicrosoft.contosob2c.exampleapp://oauth/redirect&lt;/em&gt;. The first part before the &lt;em&gt;://&lt;/em&gt; is not that important, and you can make it what you wish (though unqiue for a mobile device namespace). I would recommend you leave the last part as it is. I tried doing things like using: &lt;em&gt;://oauth&lt;/em&gt; or &lt;em&gt;://redirect&lt;/em&gt; as other articles have stated, and they cause various technical problems with libraries used.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DO NOT&lt;/strong&gt; download their sample code. I found it confusing to match up the code on the Flutter side. I suppose if you are an expert Objective-C or Android guru and have some experience with AppAuth it might help. As I did not, I experienced nothing but pain trying to make it run and work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your application should look something like this:
&lt;img src=&quot;/assets/img/2020-04-19/b2c-app.png&quot; alt=&quot;B2C Application&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;create-the-sign-in---sign-up-user-flow&quot;&gt;Create The Sign In - Sign Up User flow&lt;/h4&gt;

&lt;p&gt;I would follow &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows&quot;&gt;this&lt;/a&gt; article as the way to make this user flow. For purposes of our tutorial let’s name it “susi” and pick the following attributes:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Collect attribute:
    &lt;ul&gt;
      &lt;li&gt;Display Name&lt;/li&gt;
      &lt;li&gt;Given Name&lt;/li&gt;
      &lt;li&gt;Surname&lt;/li&gt;
      &lt;li&gt;Email Address&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Return claim:
    &lt;ul&gt;
      &lt;li&gt;Display Name&lt;/li&gt;
      &lt;li&gt;Given Name&lt;/li&gt;
      &lt;li&gt;Surname&lt;/li&gt;
      &lt;li&gt;Email Address&lt;/li&gt;
      &lt;li&gt;User’s Object ID&lt;/li&gt;
      &lt;li&gt;User Is New&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your newly created user flow should look something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/2020-04-19/b2c_1_susi.png&quot; alt=&quot;B2C Application&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;flutter-app&quot;&gt;Flutter App&lt;/h3&gt;

&lt;h4 id=&quot;create-the-app&quot;&gt;Create the app&lt;/h4&gt;

&lt;p&gt;You can use either &lt;a href=&quot;https://visualstudio.microsoft.com/&quot;&gt;VS Code&lt;/a&gt; or &lt;a href=&quot;https://developer.android.com/studio&quot;&gt;Android Studio&lt;/a&gt; to create the Flutter application. Use either one to create the basic application and we will work from there. In VS Code you can use the flutter CLI to &lt;a href=&quot;https://flutter.dev/docs/get-started/install/macos#create-and-run-a-simple-flutter-app&quot;&gt;create your project&lt;/a&gt;. Screenshots of the Android Studio way are below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/2020-04-19/android-studio-1.png&quot; alt=&quot;Android Studio 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/2020-04-19/android-studio-2.png&quot; alt=&quot;Android Studio 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/2020-04-19/android-studio-3.png&quot; alt=&quot;Android Studio 3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is the base Flutter app where we press the button that keeps a variable with how many times we have clicked it. We will use this as the starting point for our app.&lt;/p&gt;

&lt;h4 id=&quot;integrate-app-auth-into-our-app&quot;&gt;Integrate App Auth into our App&lt;/h4&gt;

&lt;p&gt;To begin modifying this simple application to suit our needs, we will learn how to use AppAuth inside our Flutter application. To make this work, we will use the &lt;a href=&quot;https://pub.dev/packages/flutter_appauth&quot;&gt;flutter_appauth library&lt;/a&gt;. First thing to do is update your pubspec.yaml file with the latest package information. If you go to the library’s &lt;a href=&quot;https://github.com/MaikuB/flutter_appauth/tree/master/flutter_appauth&quot;&gt;GitHub site&lt;/a&gt; you can find directions on how to integrate it. I will also be walking through the integration process. AppAuth is a fairly complicated library with lot of knobs and dials. The first step is to add the import of the AppAuth library and add some variables to hold all our information. We can place this at the top of the _MyHomePageState class replacing the increment variable:&lt;/p&gt;

&lt;div class=&quot;language-dart highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;FlutterAppAuth&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;appAuth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FlutterAppAuth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_clientId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'90185a76-af9b-4ff0-9fdc-55c888583e2d'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_redirectUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'com.davetest.wow://oauth/redirect'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_discoveryURL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'https://detroitdaveb2c.b2clogin.com/detroitdaveb2c.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_susi'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_authorizeUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'https://detroitdaveb2c.b2clogin.com/te/detroitdaveb2c.onmicrosoft.com/b2c_1_susi/oauth2/v2.0/authorize'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_tokenUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'https://detroitdaveb2c.b2clogin.com/te/detroitdaveb2c.onmicrosoft.com/b2c_1_susi/oauth2/v2.0/token'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_idToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_codeVerifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_authorizationCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_refreshToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_accessToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_accessTokenExpiration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_firstName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_lastName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_displayName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;dynamic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_jwt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_scopes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'openid'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For _clientId I use the application ID for the application created in the Azure B2C portal. 
For _scopes please note that in Azure B2C, a base directory instance only has the ‘openid’ scope. The discovery and endpoint URLs are worth a longer discussion. In any OAuth server you have the concept of &lt;a href=&quot;http://self-issued.info/docs/draft-ietf-oauth-discovery-01.html&quot;&gt;autodiscovery&lt;/a&gt;. Where might I find the discovery endpoint for Azure B2C? If you go to the user flow page you can see it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/2020-04-19/run-user-flow.png&quot; alt=&quot;Run User Flow&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Go take a look at yours. The important bits of mine are below&lt;/p&gt;
&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;authorization_endpoint&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://detroitdaveb2c.b2clogin.com/detroitdaveb2c.onmicrosoft.com/oauth2/v2.0/authorize?p=b2c_1_susi&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;token_endpoint&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://detroitdaveb2c.b2clogin.com/detroitdaveb2c.onmicrosoft.com/oauth2/v2.0/token?p=b2c_1_susi&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;end_session_endpoint&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://detroitdaveb2c.b2clogin.com/detroitdaveb2c.onmicrosoft.com/oauth2/v2.0/logout?p=b2c_1_susi&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The problem is if you try to use any of these endpoints, your program will work in vary degress of success across both platforms. There is a hidden gem in the &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/active-directory-b2c/signin-appauth-ios?tabs=applications&quot;&gt;article&lt;/a&gt; we used to create the application in B2C. This hidden gem says:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The token endpoint URI can be generated by replacing the Tenant_ID and the Policy_Name in the following URL:&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenEndpoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@&quot;https://&amp;lt;Tenant_name&amp;gt;.b2clogin.com/te/&amp;lt;Tenant_ID&amp;gt;/&amp;lt;Policy_Name&amp;gt;/oauth2/v2.0/token&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This format of the endpoint is different than what you see from the portal and this format was the only thing I was able to get to work across both iOS and Android reliably.&lt;/p&gt;

&lt;p&gt;Next let’s change the _incrementCounter() method to the follow code:&lt;/p&gt;
&lt;div class=&quot;language-dart highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_logIn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuthorizationTokenResponse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;appAuth&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;authorizeAndExchangeCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;AuthorizationTokenRequest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;_clientId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;_redirectUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;nl&quot;&gt;serviceConfiguration:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuthorizationServiceConfiguration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_authorizeUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_tokenUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
          &lt;span class=&quot;nl&quot;&gt;scopes:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_scopes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_processAuthTokenResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT NOTE:&lt;/strong&gt; Obviously a lot of the examples use the auto discovery URL and parameters to make things go. The ONLY way I was able to get this to work reliably with Azure B2C was to use the endpoints talked about above.&lt;/p&gt;

&lt;p&gt;In our program we can now add a few methods to decode what comes back:&lt;/p&gt;
&lt;div class=&quot;language-dart highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_processAuthTokenResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AuthorizationTokenResponse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_accessToken&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;accessToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_refreshToken&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;refreshToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_accessTokenExpiration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;accessTokenExpirationDateTime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toIso8601String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_idToken&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;idToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;//get individual claims from jwt token&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_jwt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parseJwt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;idToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_firstName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_jwt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'given_name'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_lastName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_jwt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'family_name'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_displayName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_jwt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_jwt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'emails'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;dynamic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parseJwt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'.'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'invalid token'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_decodeBase64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payloadMap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;payloadMap&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;dynamic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'invalid payload'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payloadMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_decodeBase64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;replaceAll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'-'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'+'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;replaceAll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'_'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'/'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'=='&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'='&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Illegal base64url string!&quot;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;utf8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base64Url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Let’s add the code to log out of B2C. Add a method to log out.&lt;/p&gt;
&lt;div class=&quot;language-dart highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_logOut&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;//for some reason the API works differently on iOS and Android&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;additionalParameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Platform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isAndroid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//works on Android but is missing p parameter when redirected back to authorize on iOS&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;additionalParameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;s&quot;&gt;&quot;id_token_hint&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_idToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;s&quot;&gt;&quot;post_logout_redirect_uri&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_redirectUrl&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Platform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isIOS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//missing p parameter when redirected back to authorize on iOS so the below difference&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;additionalParameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;s&quot;&gt;&quot;id_token_hint&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_idToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;s&quot;&gt;&quot;post_logout_redirect_uri&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_redirectUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;s&quot;&gt;'p'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'B2C_1_susi'&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;appAuth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;authorizeAndExchangeCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;AuthorizationTokenRequest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;_clientId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;_redirectUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;nl&quot;&gt;promptValues:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'login'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt;
          &lt;span class=&quot;nl&quot;&gt;discoveryUrl:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_discoveryURL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;nl&quot;&gt;additionalParameters:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;additionalParameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;nl&quot;&gt;scopes:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_scopes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_jwt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;A couple of words here. OAuth2 makes use of the browser for security reasons. It is a long story and a fun read if you are bored. The logout through the AppAuth library is not seemless. It logs you out, but the way to make the single API work is to redirect back to the home page so the web “page” can return something to the UI. This makes the user press the logout button, be redirected to the login page, then press the “X” or “Cancel” to get out of it and back to the app. In my humble opinion, this is a bad user experience for everyone. I have read a lot of “issue” threads on GitHub for AppAuth on the things people have done to get around it, namely forking the code and adding their own stuff. I deemed that out of scope here and wanted to keep things simple even if the log out is a little “messy”.&lt;/p&gt;

&lt;p&gt;Once again, the only thing that really works in this case is the discoveryURL parameter. This is becasue if you look at the underlying Flutter code in the flutter_appauth library, the AuthorizeTokenRequest method takes an AuthorizationServiceConfiguration that is both an auth endpoint and token endpoint. You can pass it a logout endpoint, but it doesnt work well across both platforms. Lastly, we have to do a little ‘dirty hack’ coding here. The problem is on Android I don’t have to pass the “p” parameter in to get it to work, but then it would not work on iOS. More frustratingly, if I did the opposite it would work on iOS but not Android. To fix this, I did a little “platform checking” (which in my honest opinion should be avoided when writing Flutter) and change the parameters being passed. The good news is this works like a charm.&lt;/p&gt;

&lt;p&gt;Moving forward, let’s add a bit of code to display what was was returned as well as our state. In the build() method within the _MyH, let’s replace the children property where the increment counter is with the following code:&lt;/p&gt;
&lt;div class=&quot;language-dart highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;nl&quot;&gt;children:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_jwt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Please press + sign to log in'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,)]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;[&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;'Display Name: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$_displayName&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;' '&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;'Name: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$_firstName&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$_lastName&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;' '&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;'Email: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$_email&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;' '&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RaisedButton&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;onPressed:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_logOut&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;elevation:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;child:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Logout'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And lastly in our list, to make our app run on Android we need to update &lt;a href=&quot;https://github.com/MaikuB/flutter_appauth/tree/master/flutter_appauth#android-setup&quot;&gt;update our Android’s build.gradle file&lt;/a&gt; and &lt;a href=&quot;https://github.com/MaikuB/flutter_appauth/tree/master/flutter_appauth#android-setup&quot;&gt;update our info.plist on the iOS side&lt;/a&gt;. Your shceme in both of these cases is everything you put before the &lt;em&gt;://&lt;/em&gt; in the redirect URI.&lt;/p&gt;

&lt;p&gt;This ends up looking like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/2020-04-19/azure-b2c-flutter.gif&quot; alt=&quot;Completed App&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I hope you have enjoyed this post. I will expand on this with other libraries and other B2C complexities in future posts. 
The code for this article can be found &lt;a href=&quot;https://github.com/dwhiteddsoft/flutter-azure-b2c-appauth&quot;&gt;here&lt;/a&gt;. Comment below if you have questions or concerns. Thanks for reading.&lt;/p&gt;
</description>
        <pubDate>Sun, 19 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://www.detroitdave.devhttps://www.detroitdave.dev/2020/04/simple-azure-b2c-flutter.html</link>
        <guid isPermaLink="true">https://www.detroitdave.devhttps://www.detroitdave.dev/2020/04/simple-azure-b2c-flutter.html</guid>
        
        <category>B2C</category>
        
        <category>Azure</category>
        
        <category>Flutter</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Trying Something New</title>
        <description>&lt;p&gt;Today is my birthday. I turn 50 years old today (damn!!). I spend a lot of time pouring out what I know to customers, partners, and younger programmers. My current manager encourages me to share more of what I know. Today, I have decided to start to write down some of what I do and what I know from both my time at Microsoft and things that happen outside of it.&lt;/p&gt;

&lt;p&gt;I hope it is mildly useful to anyone and I hope you like it. Maybe all it will be is simply a way for me put things down on paper so I don’t forget as I get to older. Maybe…….. where’s my pudding cup????&lt;/p&gt;
</description>
        <pubDate>Sun, 29 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://www.detroitdave.devhttps://www.detroitdave.dev/2020/03/trying-something-new.html</link>
        <guid isPermaLink="true">https://www.detroitdave.devhttps://www.detroitdave.dev/2020/03/trying-something-new.html</guid>
        
        <category>Me</category>
        
        
        <category>Personal</category>
        
      </item>
    
  </channel>
</rss>
