Author: saraford

Sara can has MVVM – Part 1 – Writing a Xamarin.Forms App

I’m big into dev journaling. I don’t know why. I have OneNotes filled of “What did I learn today”, which are probably mostly wrong from random searches. I want to break out of this “Expert Beginner” mode. And the best way I can think of that right now is through transparency.

I have a couple of physical therapy iOS apps in the app store that I’m rewriting in Xamarin.Forms. I finished these over the summer, but I didn’t like the spaghetti code mess I inflicted upon myself. I’m taking this holiday break to re-re-design my app to fit a MVVM pattern. Part of me says “it’s better to have a working app in the app store than no app” and another part of me says “what will it take for me to grok non-spaghetti code concepts??” Those two parts have finally collided.

I’ve spoken with several people over the past 6 months to help me get over this MVVM conceptual hurdle, which you’ll read about in Part 2. To be clear, I get commanding and databinding. What I’ve always struggled with is how to get that data consumed by other parts of the app (e.g. a service, but how does a service work? Is it a static class? Is it a singleton? etc.)

Huge shout out and thank you to Matt Soucoup for being my human StackOverflow! Matt and I have been recording code review sessions together where I get to ask all of my n00b questions “Why are you using a NavigationPage and not just a regular ContentPage?”,  “Oh is that what that xmlns stands for!” and “I didn’t realize databinding took care of that automatically!” If you’re doing Xamarin work, stop reading my blog and go check out his at https://codemilltech.com/

Aside: Writing code is similar to writing an essay. There are so many different ways to express one’s thoughts. So many different ways to solve logic problems. So many different ways to code. Always fascinating to what someone else write code.

What I’m building

I’m rewriting “OnMyNerves” (a nerve desensitization therapy timer app – it’s really just a glorified timer). The user enters several Fabrics (that are used to desensitize the nerve) into a ListView. The user enters the Name and Seconds for each fabric. These fabrics are persisted on disk, so the user enters their “daily workout plan” only once.

This Fabric ListView is found under the Settings tab.

Mockup Showing list of fabrics

After the user populates the Settings, the user taps on the Timer page. When the user hits play, the timer starts for that fabric. In the screenshot below, Fabric 1 has 7 seconds remaining.

Mockup showing current Fabric timer progress

And the end, an alarm plays along with a couple of message boxes for user prompts (trust me the UX will make sense when we get there).

After the user dismisses the 2 message boxes, the timer goes onto the next fabric. When the timer has gone through all fabrics in the list, the sessions is saved (this is new in this Xamarin.Forms rewrite).

Each section below contains a “What I learned” retrospective.

  1. Creating a two page Tabbed control
  2. Writing up a ViewModel for Xamarin.Forms pages
  3. Adding XAML Compiling

To follow along for this blog post, check out all the tags (no pun intended) using git tag at   https://github.com/saraford/ListViewInsideTabbedControl

1 – Creating a two page Tabbed control

To see the completed code for this step:

​​​​​​git checkout tags/two-page-tabbed-control

Let’s start with the App()  constructor.

public App()  {

            InitializeComponent();

            var page1 = new Page1() {
                // needed to give the tabbed page a name
                Title = "Page 1"
            };
            var page1Nav = new NavigationPage(page1);

            var page2 = new Page2() {

                // needed to give the tabbed page a name
                Title = "Page 2"
            };
            var page2Nav = new NavigationPage(page2);

            // look! no corresponding .xaml file
            var tabbed = new TabbedPage();
            tabbed.Children.Add(page1);
            tabbed.Children.Add(page2);
            MainPage = tabbed;
}

This code will produce the following app:

Initial 2 pages in a Tabbed control non-MVVM

What did I learn?

  • If you look in the solution, you’ll discover that I’ve deleted the ListViewInsideTabbedDocumentPage.xaml file. Turns out you don’t need a “physical” .xaml file to go along with your tabbed page. I was surprised by this, asking, “But if I get rid of the .xaml file, that implies I’ll never have to make any XML changes?” Well, it turns out this is okay. The tabbed page really is a ‘holder’ of other pages, and doesn’t have a much of a UI other than the tabs. So in this case it is a lot easier to create the tabbed page all in C# rather than using XAML. You can just queue it up in a code behind. You can do more UX stuff with C# than you can do in XAML, but you’d really have to be getting into it at that point.
  • I also learned that you can have interactive tabs that don’t have text or images! So if you’re wondering, “why aren’t my tabs showing up?” They might be, even if you didn’t specify a Title or Image. Just look closely or tap 🙂
  • You’ll read about NavigationPage vs just new’ing up a ContentPage tomorrow

2 – Wiring up the ViewModel for our Xamarin.Forms pages

To see the completed code for this step:

git checkout tags/viewmodel-created

I remember someone telling me years ago that you always want to use a MVVM framework. This section explains why using a MVVM framework helps prevent you from rewriting code. BTW I’m the *worst* when it comes to this…I rewrite things, crazy things, all the time because I never stop first to check if there’s something I could reuse.

Step 1 – install Refactored.MvvmHelpers by James Montemagno. Install this in your PCL.

nuget installing Refactored.MvvmHelpers

This MvvmHelpers library gets you a couple of useful things

  • ObservableObject – you’ll see this more when we start to work on the ListView, but you know how you have to implement INotifyPropertyChange and use properties for databinding? That’s what this class does for you! No more hours wasted trying to debug “why isn’t my data refreshing?”

Looking at ObservableObject class

  • BaseViewModel – In a few minutes, you’ll have your ViewModels inherit from this class. BaseViewModel gives your ViewModels some common properties that will be used in practically all views, like Title and IsBusy. All you need to do is databind them. But what’s even better is that BaseViewModel also derives from ObservableObject, so again, you don’t have to redo INotifyPropertyChange in each of your ViewModels.

Step 2 – Next let’s refactor our solution

  • Move Page1.xaml and Page2.xaml into a new folder called Views. Next don’t forget to update the namespace from ListViewInTabbedDocument to ListViewInTabbedDocument.Views
    • This gets me every time “I moved the file but yet VS still knows where to find it!” So rename your namespace Every. time. sigh.
    • the namespace in the xaml, e.g.  x:Class=”ListViewInTabbedDocument.Views.Page1″>
  • Create a new folder call ViewModels. Add two classes, PageOneViewModel.cs and PageTwoViewModel.cs, creatively, into this ViewModels folder. (and please please please let Ready Play One movie be good!)

Step 3 – Have the PageOneViewModel look like the code below

Note the Navigation class in the constructor. You’ll pass this Navigation class in from the View so that the ViewModel will be able to call Push and Pop. More on that later.

Yes, I’m putting the View’s Navigation property into the view model… not exactly a pure separation of concerns. But this actually works out quite nicely! And it’s my next blog post (Part 2) that I’m desperately trying to grok, i.e. how the TimerPage gets the databinding’ed (databound? databinded?) data.

Also note the Title property being set. This comes from BaseViewModel.

using MvvmHelpers;
using Xamarin.Forms;

namespace ListViewInTabbedDocument.ViewModels {

    class PageOneViewModel : BaseViewModel  {

        private INavigation Navigation;

        public PageOneViewModel(INavigation Navigation) {

            Title = "Page One from VM";
            this.Navigation = Navigation;
        }
    }
}

Aside: my first CS prof told us never use the same variable name as in the parameter of a method or constructor as the class fields / properties. But this in the days of Turbo Pascal and I don’t recall if we had a `this` keyword back then.

Step 4 – Let’s have the Views create their ViewModels

The ViewModels will need to pass in the Navigation and setup the ViewModel as the binding context. So in the Views code behind…

public Page1 () {

   InitializeComponent();

   var pageOneViewModel = new PageOneViewModel(this.Navigation);
   this.BindingContext = pageOneViewModel;
}

Step 5 – Use databinding for the Title

Now to test we’re actually getting content from the ViewModel binding, update the Page1.xaml as follows

<ContentPage.Content>
        <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
            <Label Text="{Binding Title}" />
        </StackLayout>
</ContentPage.Content>

And you’ll get the following. Notice the new text.

2 Pages using MVVM

Rinse and repeat for Page2.

The reason why I like doing things twice by having two pages (and yeah it’s a moot point since a tabbed control needs 2 or more) is that I can verify my blog posts by following my own directions for Page2.

What did I learn

  • First and more importantly, Alt+Enter in Visual Studio for Mac is the equivalent of Ctrl+. in Visual Studio.
  • I finally had a chance to ask all my embarrassing questions, including “When do you need to put the assembly name in the namespace? Is there something special about the name `local`? And what exactly is `xmlns`?   For example…”
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:ex="clr-namespace:OnMyNerves.Views;assembly=OnMyNerves"
    x:Class="OnMyNerves.Views.SettingsPage"

Here’s the breakdown…

  • `x:Class` is for the code behind
  •  “xmlns:x” which is the standard XAML namespace – which defines things like x:Name
  • “xmlns:local” is used when you’re going to use something in a different class somewhere that’s not in code behind. There’s nothing special re local. In this example, I’m using “xmlns:ex”.
    • Usually you’ll see both the `clr-namespace` and `assembly` defined
    • Wouldn’t need assembly if it is in the same an assembly, but if it is part of a 3rd party control, etc. you have to have it. Never hurts to be explicit.
  • “xmlns” – this stands for “XAML Namespace”, akak the base namespace. Means you can get everything that’s available in the Xamarin Forms namespace without any prefix, like StackLayout. Otherwise, prefixing these controls all over the place would get really old really fast.
  • “x.Name” – that’s part of the overall xaml namespace, which is different from the base namespace.

The more you know!

3 – XAML Compiling

To follow along:

git checkout tags/xaml-compiling

In App.xaml.cs, add the assembly attribute before the namespace.

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace ListViewInsideTabbedDocument {

What I learned

  • When it is on, in the final package XAML is complied down to IL. Otherwise, it would have to inflate and parse at runtime.
  • And XAML compiling does help during debugging … it will throw compile errors if you have any errors in your XAML (like typos) – that way you don’t have to wait until you actually load up the page at debug-time before it crashes on you.

Next blog post is about how to wire up a ListView instead the TabbedControl. Not sure why I called my project ListViewInsideTabbedDocument – that’s some old muscle memory from Visual Studio taking over my typing!

Calling an Azure AD B2C-secured ASP.NET Core Web API 2 from JavaScript

Wow that’s a blog post title I never thought I’d write considering I started the year blogging all the things related to Git and GitHub! 🙂  I should come full circle and have Hubot call a B2C-secured API using coffeescript! Hmm…

In my previous post, you saw how to create a new ASP.NET Core Web API 2 and secure it using Azure AD B2C. Today’s blog post discusses how to call this API from a Single Page Application (think javascript).

Why not just make the call as before? Because you’ll get this error message:

Error calling the Web api:
error

If you open up the Developer Tools – Console window, you’ll see the full error message:

Failed to load https://localhost:44332/hello: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin http://localhost:6420 is therefore not allowed access. The response had HTTP status code 404.

Using CORS on an ASP.NET Core Web API 2

I’m following this how to article on enabling CORS in an ASP.NET Core application.

Using my example API (here’s the diff), you’ll first want to add CORS to your ConfigureServices() method in Startup.cs

public void ConfigureServices(IServiceCollection services) {
  services.AddCors();

Next, you’ll want to configure Cors in your Configure method

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {
  app.UseCors(builder =>
    builder.WithOrigins("http://localhost:6420").AllowAnyHeader().AllowAnyMethod());

And that’s it! Now run your application.

Note that…

I had to use AllowAnyHeader() and AllowAnyMethod(). I thought this might be implied since the article didn’t call it out. I’m also curious if there’s a way to tighten this even more. I practice paranoia-driven development.

Updating the Single Page App to call the B2C protected Resource

I’m using the Azure AD B2C MSAL.js sample. Why this sample? No particular reason. It was the just first B2C javascript sample I learned.

First, you’ll want to register this app in your B2C Tenant. Don’t forget to provide API-level access to this app.

Clone the repo, open in VSCode, and update the B2C coordinates in index.html in this section. For b2cScopes and webApi, I left the ones from the previous blog post.

clientID:'your application id for your SPA',
authority:"https://login.microsoftonline.com/tfp/.onmicrosoft.com/",
b2cScopes: ["https://.onmicrosoft.com/HelloCoreAPI/demo.read"],
webApi:'https://localhost:44332/hello',

That’s it! To start your SPA, go to the command line and in the same directory as server.js run node server

Now log into the web application and call the API. And you’ll see “Hello there!” returned!

Note: if you forget to provide API-level permissions to the SPA in the Azure B2C portal, you’ll see an error message that popups are being blocked. Open the Developer Tools – Console window and click the link for the full error message.

Securing an ASP.NET Core Web API 2 using Azure AD B2C

In a previous post you saw how to secure and call an ASP.NET Web API using Azure AD B2C. Today’s post is how to secure an ASP.NET Core Web API 2. This blog post walks you through the steps from File – New – Project to using Postman to test your API with an access token. Here’s the official ASP.NET Core sample

Create the project

Since this is my first ASP.NET Core project, I spent some time playing with the getting started first-web-api tutorials.

  • File – New – Project – .NET Core – ASP.NET Core Web Application
  • I called mine HelloCoreAPI, because in my previous post I had registered a HelloAPI and you need to use an unique App ID URI
  • Select Web API
    • Make sure ASP.NET Core 2.0 is selected (I’m using VS 2017 so it’s the default)
    • Make sure No Authentication is set

And hit F5 just to make sure things are working.

Create the /hello endpoint

I spent some time exploring the documentation on ASP.NET Core routing.

  • I deleted the default ValuesController since I won’t be using it
  • Right click on the Controllers folder, and add a new API Controller – Empty
  • Call it HelloController – just like picking up your mouse and saying “Hello Computer!”

I’ve setup my route to look like

 

[Route("hello")]
[HttpGet]
public IActionResult Hello() {
    return Ok("Hello There");
}
  • Open launchSettings.json and for both profiles (or just the IIS Express profile) change “launchUrl” to “hello” – the preceding ‘/’ is handled by the “ApplicationURL”

Hit F5 and see “Hello there!”

Enable https

I happened to see this on twitter today while writing this blog post. For cross-platform support, check out this blog post: https://blogs.msdn.microsoft.com/webdev/2017/11/29/configuring-https-in-asp-net-core-across-different-platforms/

  • Go to Project Properties – Debug and check Enable SSL
  • In `launchSettings.json` change both the `applicationURL` to the new https address

According to the enforcing SSL docs, you should also do

services.Configure<MvcOptions>(options =>
{
     options.Filters.Add(new RequireHttpsAttribute());
});

F5 to make sure everything’s good

Register the API application in B2C

  • Go to the Azure Portal and make sure you are in the right tenant!
  • In B2C, go to Applications and click New Application
  • Give the application a name you can identify, like Hello Core API
  • This is a Web API so click Web API
  • Under reply URL use the https address that opens when you hit F5, e.g. https://localhost:44332
  • Under API ID URI, give it a unique name. Since I have a previous example, I shall call this API, creatively, HelloCoreAPI
  • Hit create
  • Create the “demo.read” scope under Published Scopes

Enter the B2C coordinates

In appsettings.json add the following:

"AzureAdB2C": 
  {
    "Tenant": "<your tenant name>.onmicrosoft.com", 
    "ClientId": "<the application id you just registered>",
    "Policy": "<your sign up sign in policy e.g. B2C_1_SiUpIn>",
    "ScopeRead": "demo.read"  
  },

Setup Middleware

  1. in Startup.cs – ConfigureServices(), we’ll want to initialize the JWT Bearer middleware to validate tokens since this is an ASP.NET Core Web API.
public void ConfigureServices(IServiceCollection services) {
  services.AddAuthentication(options => {
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    })
      .AddJwtBearer(jwtOptions => {
         jwtOptions.Authority = $"https://login.microsoftonline.com/tfp/{Configuration["AzureAdB2C:Tenant"]}/{Configuration["AzureAdB2C:Policy"]}/v2.0/";
         jwtOptions.Audience = Configuration["AzureAdB2C:ClientId"];
         jwtOptions.Events = new JwtBearerEvents
         {
            OnAuthenticationFailed = AuthenticationFailed
         };
    });

  services.AddMvc();
}

2. In Startup.cs, add the AuthenticationFailed method for locally debugging this sample only. Note how the repo readme instructs you not to use this handler in production scenarios.

3. In Startup.cs, create a public static field called ScopeRead

4. In Startup.cs Configure() add

ScopeRead = Configuration["AzureAdB2C:ScopeRead"];
app.UseAuthentication(); 
...
app.UseMVC();

Secure the API call itself

  1. Add the Authorize attribute to the class level in HelloController.cs
[Authorize]
public class HelloController : Controller

2. Make sure the user has the right scopes for the API.

public IActionResult Hello() {

  var scopes = HttpContext.User.FindFirst("http://schemas.microsoft.com/identity/claims/scope")?.Value;
  if (!string.IsNullOrEmpty(Startup.ScopeRead) && scopes != null && scopes.Split(' ').Any(s => s.Equals(Startup.ScopeRead))) {
     return Ok("Hello There");
  }
  else
  {
     return Unauthorized();
  }
 }

Whenever I’m debugging a B2C call to an API, I set a breakpoint inside the API to make sure I know which Unauthorized I’m debugging.

If you hit F5, you’ll get a 401 unauthorized error, because this user agent isn’t authorized, so any breakpoints you set within the method won’t get hit.

How to test your API

From a previous blog post, you can use the Policy Run Now feature and Postman to debug.

My code sample is at https://github.com/saraford/HelloCoreAPI

My API app registration in the B2C portal looks like

ASP.NET Core API app registration in B2C

Next blog post: How to call this ASP.NET Core Web API from a Single Page Application.

Testing a B2C secured Web API using Postman

In my post yesterday on Securing a Web API, I asked how might I test my API after securing it, since I didn’t have a client app created yet.

Of course, there is a way using Postman.

I’ve mentioned previously how to use the “run now” policy feature to test your policy and review your tokens. That previous blog post used a web application. Today’s blog posts uses a native app as the selected application.

Go to your B2C_1_SiUpIn policy:

  1. Under Select application, chose Hello API WPF App. 
  2. Under Select reply url, choose the https url
  3. Expand Access Tokens and under Select resource, select Hello API (or whateer name you gave your API from yesterday’s blog post). Make sure all the scopes are selected.

Here’s what my Run Policy Settings look like.

Sign Up or Sign In policy run now page
Click Run now. You’ll see a new browser tab appear. Copy the resulting URL and open up your favorite flavor of notepad.

access token in the reply url

Make sure you only copy the access token and none of the other parameters that come after the access_token. This had me scratching my head for a good half-hour.

Open up https://jwt.ms and paste in the access token to confirm it all looks good and contains the claims you’re Hello API is expecting, e.g. “read”

reviewing scopes in jwt.ms

Next, fire up Postman. Also, make sure your Hello API project is running 🙂

I’m still new to Postman, so YMMV. If you have a different way of using Postman for this scenario, please let me know!

  1. Choose GET and insert the URL for your Hello API /hello endpoint.
  2. Under Headers, type in Authorization
  3. For its value, type in Bearer then the access token.

Postman with a bearer tokenAnd if all is setup correctly, you’ll get the expected response!

I’m still working on a blog post on how to debug all these steps for creating a client application and an API for use with B2C. Stay tuned!

Securing and calling a web API using Azure AD B2C

This blog post walks you through creating and securing an ASP.NET Web API to work with B2C. You’ll call your new API from an existing B2C sample WPF application. I chose the WPF application example since this type of client app requires the fewest line changes to setup.

Note: The Azure Docs are securing a web API and calling a web API. This blog post is my “if I could go back in time, here’s what I would tell myself.”

When I first started learning Azure AD B2C, I thought it was adequate for 100 lv content that the samples to only contain a client application to obtain an id token. Perhaps this makes sense for the very first module in a B2C course. However, most apps want to do more than just authenticate and show your display name from the id_token. If you want to do more than just greet your users, your client app need to acquire an access token so it can put it to use, e.g. accessing some resource like an API.

btw: if you are only using an id token, I’d love to learn more about your scenarios!

Note you have to register your own APIs with B2C. You can’t use someone else’s API for demo purposes because the client ID and tenant name would be different. Trust me I went down this path several times before the “oh yeah – that’s right” moment finally hit home and stuck with me.

Demo code

The API in this sample returns a Hello <username> if the user is authorized.

The code sample that goes alongside this blog post is at https://github.com/saraford/HelloAPI-blog-post

Creating the Web API

  1. Open a new instance of Visual Studio. (In this example, I’m using Visual Studio 2017, but if there’s interest for 2015 steps, lmk!)
  2. Go to File – New – Project and choose Web – ASP.NET Web Application (.NET Framework)
  3. Choose Web API
  4. Name your project HelloAPI and click OK
  5. Leave authentication as No Authentication – otherwise, it installs Microsoft.Owin.Security.ActiveDirectory that uses the WindowsAzureActiveDirectoryBearerAuthentication middleware that doesn’t work with B2C tokens.

Create a route

Before we jump into authorizing our route, let’s make sure our API works properly.

  1. On the Controllers folder, right-click and select Add – Controller 
  2. Select Web API 2 Controller – Empty and then click Add
  3. Name the controller HelloController

Next, we’ll add a new route


[Route("hello")]
[HttpGet]
public string Hello()
{
   return "Hello there!";
}

Now run your application. Add the `/hello` endpoint in your browser. You’ll be prompted to open a “hello.json” file.

For my setup, this file opens in VS Code and I see “Hello there!” returned.

Configure SSL

  1. Open the Properties Tool Window for the project, i.e. go to View – Properties Window (or press F4 on the project in solution explorer)
  2. Set SSL Enabled to true
  3. Copy the resulting SSL Link that appears below
  4. Go to the Properties page by right clicking on the project name in solution explorer and selecting Properties (or pressing Alt+Enter)
  5. On the Web side-bar tab, paste in the SSL link in the Project Url
  6. Click Create Virtual Directory – this step may be optional, I’m not sure.

Run your project and hit the /hello endpoint just to verify you are all set with SSL.

Now that the API is working properly, we can now move onto the next step: authorizing only those users with certain scopes in their access tokens to access the API.

Register the API in Azure AD B2C

Although you can register the API in the Azure portal at any time, I prefer to create the project first. It just keeps me grounded as to what I’m doing.

  1. Go to the Azure Portal – https://portal.azure.com/
  2. Make sure you are in the correct tenant you want to use.
  3. Register a new Web API
    1. Click Applications –  Add.
    2. Give it a reader-friendly name, like `Hello API for Demo`
    3. Click Yes for Web App / Web API
    4. For Reply URL, paste in the SSL URL you are now using from the Properties page (the Alt+Enter page) along with the endpoint e.g. `https://localhost:44326/hello`
    5. For App ID URI, provide a unique ID, e.g. `helloAPI` – this must be unique across all your B2C-registered applications in your tenant.
    6. Keep Native client as No.
    7. Click Create and wait a couple of seconds.
  4. Add scopes
    1. Click on your newly registered application in the portal, i.e. `Hello API for Demo`
    2. Click Published scopes 
    3. Under Scope, give it the name `read` and a description `yet another read access`

If you have any issues following these steps, please check out my previous blog post.

Install the middleware 

Back to Visual Studio!

The next steps are about setting up the middleware – aka the libraries for the Web API that talk to B2C, parse tokens, etc.

Note: OWIN is a specification, whereas “Katana” is the implementation of OWIN for .NET, but it seems a lot of people say “OWIN” to represent the implementation that is Katana.

You install all the necessary OWIN / Katana packages from the Package Manager Console. The blog post uses the nuget command line.

Note: if you decided to keep it all into one big solution, you’ll need to specify the project name (`Install-Package Microsoft.Owin.Security.OAuth -ProjectName HelloAPI`) or switch to that project in the nuget Package Manager Console dropdown. This got me a few times at first. I didn’t realize I was installing to the wrong project.

1. Run the command

Install-Package Microsoft.Owin.Security.Oauth

This will install at least the following dlls:

  • Owin
  • Microsoft.Owin
  • Microsoft.Owin.Security
  • Microsoft.Owin.Security.Oauth
  • And possibly others

2. Run the command

Install-Package Microsoft.Owin.Security.Jwt

This will install “system.identitymodel.tokens.jwt” – this is a lower layer component that verifies tokens.

3. Run the command

Install-Package Microsoft.Owin.Host.SystemWeb

This loads the OWIN startup.cs into pipeline. Otherwise, you’ll get the dreaded “unauthorized” generic error message.

4. Run the command

Install-Package Microsoft.Owin.Security.OpenIdConnect

This is needed for the OpenIdConnectCachingSecurityTokenProvider class, which is needed for refreshing B2C tokens. You’ll add this class further below.

Add authorization code to the API

To the code!

Next, let’s setup the OWIN middleware.

1. The OWIN middleware needs to be configured at Startup. Otherwise, you’ll get the error:

[EntryPointNotFoundException: The following errors occurred while attempting to load the app.
 - No assembly found containing an OwinStartupAttribute.
 - No assembly found containing a Startup or [AssemblyName].Startup class.

This was a helpful article: OWIN Startup Class Detection

2. At the root project level in Solution Explorer, right-click and Add a new class. Choose OWIN Startup class. Rename the class to Startup.cs

3. Add the following code to the constructor:

// The OWIN middleware will invoke this method when the app starts
public void Configuration(IAppBuilder app)
{
  ConfigureAuth(app);
}

4. Change the class to partial

public partial class Startup

 

5. Go to the App_Start folder and add a new class called OpenIdConnectCachingSecurityTokenProvider.cs. Paste the code from an existing sample. Make sure to change the namespace to match yours. This class is needed to refresh B2C tokens.

6. In the App_Start folder and add a new class called `Startup.Auth.cs`

  • Change this to partial. Why a partial class? It seems to be the design standard I’m seeing other samples use, but there’s no reason you can’t keep it all in the Startup.cs class (not that I’m aware of).
  • Change the namespace from `HelloAPI.App_Start` to `HelloAPI` to match the Startup.cs class
  • Add the following code into your Startup.Auth.cs class to configure the OWIN middleware (notice how this code uses your newly added OpenIdConnectCachingSecurityTokenProvider)
public partial class Startup
{
  // These values are pulled from web.config
  public static string AadInstance = ConfigurationManager.AppSettings["ida:AadInstance"];
  public static string Tenant = ConfigurationManager.AppSettings["ida:Tenant"];
  public static string ClientId = ConfigurationManager.AppSettings["ida:ClientId"];
  public static string SignUpSignInPolicy = ConfigurationManager.AppSettings["ida:SignUpSignInPolicyId"];
  public static string DefaultPolicy = SignUpSignInPolicy;

  /*
  * Configure the authorization OWIN middleware
  */
  public void ConfigureAuth(IAppBuilder app)
  {
    TokenValidationParameters tvps = new TokenValidationParameters
    {
      // Accept only those tokens where the audience of the token is equal to the client ID of this app
      ValidAudience = ClientId,
      AuthenticationType = Startup.DefaultPolicy
     };

     app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
     {
         // This SecurityTokenProvider fetches the Azure AD B2C metadata &amp;amp;amp;amp; signing keys from the OpenIDConnect metadata endpoint
         AccessTokenFormat = new JwtFormat(tvps, new OpenIdConnectCachingSecurityTokenProvider(String.Format(AadInstance, Tenant, DefaultPolicy)))
     });
   }
}

Now ctrl+. All the things! Or simply just use these using statements in Startup.Auth.cs

using HelloAPI.App_Start;
using Microsoft.Owin.Security.Jwt;
using Microsoft.Owin.Security.OAuth;
using Owin;
using System;
using System.Configuration;
using System.IdentityModel.Tokens;

7. In Web.Config, add the following keys to your <appSettings>

<appSettings>
 <add key="ida:AadInstance" value="https://login.microsoftonline.com/{0}/v2.0/.well-known/openid-configuration?p={1}" />
<add key="ida:Tenant" value="dorfarasB2CTenant.onmicrosoft.com" />
<add key="ida:ClientId" value="b32e98b0-16ec-46ae-9e6a-4ccb0286e9a3" />
<add key="ida:SignUpSignInPolicyId" value="b2c_1_SiUpIn" />

Let’s pause here and make sure everything runs. We just want to make sure the OWIN middleware is configured properly to run at startup.

Add authorization verification to the route

1. In HelloController.cs, add the following constants at the top of the class

 // OWIN auth middleware constants
 public const string scopeElement = "http://schemas.microsoft.com/identity/claims/scope";
public const string objectIdElement = "http://schemas.microsoft.com/identity/claims/objectidentifier";

2. Secure your route by adding the [Authorize] attribute. I got this information from the ASP.NET Web API 2 attribute routing docs.

[Authorize]
[Route("hello")]
[HttpGet]
public string Hello()

3. Add the code to verify the access token contains the correct scopes. And if so, might as well display the name while we’re at it!

public string Hello()
{
   HasRequiredScopes("read");
   string name = ClaimsPrincipal.Current.FindFirst("name").Value;
   return "Hello there! " + name;
}

4. Add the HasRequiredScopes() method below the Hello() method – this is the method the B2C samples are using right now. YMMV.

// Validate to ensure the necessary scopes are present.
private void HasRequiredScopes(String permission)
{
  if (!ClaimsPrincipal.Current.FindFirst(scopeElement).Value.Contains(permission))
  {
     throw new HttpResponseException(new HttpResponseMessage
     {
       StatusCode = HttpStatusCode.Unauthorized,
       ReasonPhrase = $"The Scope claim does not contain the {permission} permission."
     });
  }
}

5. ctrl+. to add `using System.Security.Claims;` for the ClaimsPrincipal object

Let’s run your project to verify everything builds and launches. Don’t try to hit your endpoint yet. You are not authorized yet so it won’t work.

BTW: if someone knows a better way to test everything at this point, please let me know! 
Update: Here’s a new blog post how to test your new API using Postman

Setting up the client to talk to your new API Endpoint

  1. Download or clone the B2C sample WPF project from https://github.com/Azure-Samples/active-directory-b2c-dotnet-desktop
  2. Register this in the Azure Portal (if you’ve already registered this from a previous sample, you can still use that registration)
    1. Make sure you are in the right tenant!
    2. Go to Application – Add
    3. Give your WPF app a friendly name, e.g. ​`​Hello API WPF App`
    4. Click No for Web App / Web API
    5. Click Yes for Native client
    6. Give it a custom Redirect URI of `com.onmicrosoft.<your-tenant-name>.desktopapp://redirect/path`
    7. Click Create
    8. Wait a couple of seconds and open your app Hello API WPF App registration page
    9. Click on API access (preview) then click Add
    10. Select your HelloAPI in the dropdown and make sure the `read` scope is selected
    11. Click OK
  3. In App.xaml.cs
    1. Update the Tenant name to use your tenant name
    2. Update the ClientId to match your Application ID you got from registering your app in the portal
    3. Update your policies to match the ones you’ve created from my previous blog posts.
  4. In App.xaml.cs update the ApiScopes and ApiEndpoint to use you API endpoint and your defined scope, e.g.

 

public static string[] ApiScopes = { "https://dorfarasB2CTenant.onmicrosoft.com/helloAPI/read" };
public static string ApiEndpoint = "https://localhost:44326/hello";

Note: I like to comment out the previous ApiScopes and ApiEndpoint, so in case I need to debug, it’s easy to switch back to a working version.  Note: I like to comment out the previous ApiScopes and ApiEndpoint, so in case I need to debug, it’s easy to switch back to a working version.

5. Run the client app. (Sign out if applicable) and sign in. Now click Call API, and you should see “Hello there! <Display name!>”

Reference

Here’s my API Registration in case it helps you to debug.

Hello API registration in the Azure Portal with Reply URL showing the SSL URL with endpoint and the App ID URI of `helloAPI`

Achievement unlocked: Since I’m historically a client developer, this is my first time blogging about creating an API!

How to review your Azure AD B2C tokens using Policy – Run Now and jwt.ms

On the Policy window, you’ll see this Run Now button at the bottom of the screen.

B2C Sign In or Sign Up Policy window

The Policy – Run Now button opens the URL shown in the Run now endpoint (shown above the button) in a new tab browser. This call to B2C the /authorize endpoint displays the familiar login window.

Sign in with local account screen

Once you successfully login, B2C will send the token (either id_token or access_token) to the selected Reply URL listed on the Policy – Run Now page. If you add `https://jwt.ms` to one of your applications reply URLs, you’ll be able to select it from the dropdown.

Select application and Select reply URL for Policy - Run Now

Recall you can add a reply URL to an application by going to its registration page, e.g. “drofaras B2C web app”, and adding https://jwt.ms to the list of Reply URLs.

Since this example requests an id_token be sent to https://jwt.ms, the following URL is shown in the browser.

https://jwt.ms/#id_token=eyJ0eXAiOiJKV1QiLCJhbGc...

I’ve learned that the # is a Fragment Identifier, so anything after the # can only be used client-side. The website jwt.ms takes this id_token and decodes it for you…

jwt.ms showing decoded

What about access tokens?

Yep, you can also test out access tokens as well as id tokens.

Go back to the Policy settings page and expand the Access Token area. Select the resource, e.g. a Web API, and the desired scopes you want to verify.

specifying access tokens for Policy - Run Now

Clicking run now will open jwt.ms, but nothing will be displayed. The website is only looking for id_tokens. But, if you copy everything after the #access_token in the url

https://jwt.ms/#access_token=eyJ0eXAiOiJKV1QiL...

and paste that in directly to jwt.ms, you’ll see the access token decoded.

Other usages for Run Now

Suppose you’ve made some changes to your policy and you want to verify things are setup the way you want from within the Azure portal. Examples include

  • You’ve added a sign-up claim and you want to verify this claim appears correctly in the id_token.
  • You’ve added a new Social Identity Provider and want to quickly test you can sign in.
  • You’ve added a new scope in the access token and want to verify it in your awaiting server listed in the Reply URL

Note

Something that confused me early on is I tried to test my policy immediately after I created it, meaning that I didn’t have a localhost server up and running yet. When I ran the policy, I got the following

can't reach this page

Now of course this makes sense, since I’d need to have http://localhost:50185 (from image) running… however, I could have still verified my tokens by coping everything from the # token portion of the URL, e.g.

http://localhost:50185/#id_token=eyJ0eXAiOiJKV...

and pasting it into jwt.ms, even though my reply url server isn’t running.

FWIW

At first glance, I thought the Policy – Run Now button meant to “run” the policy as in “Visual Studio F5 Run” the policy – as if creating it, but that’s not what’s happening here. 

At second glance, I thought the Run now button performed more logic behind the scenes, but it is just calling that /authorize endpoint in a new tab. 

 

 

How to use https://jwt.ms/ to decode JSON Web Tokens

tl;dr The site https://jwt.ms allows you to decode tokens and the tokens never leave your browser.

Once I got a handle on what access tokens are used for, the next step became how do I know what is inside an access token? For example, is the app telling me that the user is unauthorized because they are not signed in? Or is it because a scope is missing or contains a typo in the access token?

What’s a JSON Web Token?

From the Azure AD B2C documentation

Many of the tokens that Azure AD B2C issues are implemented as JSON web tokens (JWTs). A JWT is a compact, URL-safe means of transferring information between two parties. JWTs contain information known as claims. These are assertions of information about the bearer and the subject of the token. The claims in JWTs are JSON objects that are encoded and serialized for transmission. Because the JWTs issued by Azure AD B2C are signed but not encrypted, you can easily inspect the contents of a JWT to debug it. Several tools are available that can do this, including jwt.ms. For more information about JWTs, refer to JWT specifications.

> A JWT is a compact, URL-safe means of transferring information between two parties. 

First, a JSON Web Token is a token (i.e. a string of numbers and letters) that when decoded will present data in JSON format.

> JWTs contain information known as claims.

The content that we’re interested in right now is called “claims”. This is terminology that will make sense once you see a JWT decoded.

> The claims in JWTs are JSON objects that are encoded and serialized for transmission. 

Yep, what I said earlier.

> Because the JWTs issued by Azure AD B2C are signed but not encrypted

You’ll see in a bit where the JWT is signed.

What does a JSON Web Token look like in jwt.ms?

Fortunately the documentation contains a couple of different sample JWTs: an id token and an access token. Both are JWTs, but have different “claims” and different purposes.

The differences between an id token and an access token start to make a lot more sense once you see them decoded and compare them.

Let’s start with an id token. Cut and pasting the sample id token from the docs into jwt.ms shows the following:

Color coded JWT token text

Note the text at the bottom of the image “This is an Azure AD B2C token.” The jwt.ms site also figures out if you’ve supplied an Azure AD v1 token or Azure AD v2 token. In the future, this will be important to verify in case your token isn’t being accepted somewhere.

Also the token is color-coded. These colors are represented in the lower half of the screen.

token broken down into color coded JSON sections

The items in blue are the claims. If you click on the Claims tab, you’ll see the descriptions of these claims.

claims descriptions shown

The last item in the list is idp​ meaning the token “claims” to have come from the identity provider facebook.com.

It is common for an id tokens to contain something like a “name” claim which is used to show your Display name after you log in, e.g. “Hi Sara!” The app is getting the Display name from the id token claims.

How does an access token differ from the id token in jwt.ms?

The best way to see the differences is to use the access token generated from my previous blog post.

For example, if I view the access token from my previous blog post, I can see the scopes I specified for access to the API. These scopes are claims for the token.

scp claim showing HelloRead and Hl

This is important because the next time I get an unauthorized access error trying to call an API, I can check whether the access token contains the right scopes.

Remember those “application claims” you checked on your Sign In Or Sign Up policy, e.g. Display Name and Postal Code?

Postal Code checked for Application claims

well, here you go! they are shown as claims.

Display name claim Smo Jo and postalCode claim 98052

There are other claims that are important to know as well. From  https://aka.ms/b2caccesstokens

  1. aud – Audience – The application ID of the single resource that the token grants access to.
  2. azp – Authorized Party – The application ID of the client application that initiated the request.

BTW: SmoJo was my high school nickname, like FloJo, but not as fast =)