Authenticate an Azure Function with Azure Active Directory

Today is the first working day of a new year. I thus decided to work on a question raised by our senior developer on the eve of the new year: How do we authenticate an Azure Function?

The authentication tool that I am using is the Azure Active Directory (Azure AD). Azure AD provides an identity platform with enhanced security, access management, scalability, and reliability for connecting users with all our apps.

The Azure Function that I’m discussing here is the HTTP triggered function with .NET runtime stack and Windows as the OS.

Webhook + API: Creating a function which runs when it receives an HTTP request.

Once the trigger is created, we can proceed to setup authentication for the Function.

Firstly, under the Integrate section, we need to change the Authorization level of the Function to be “anonymous”, as shown in the screenshot below. This is because for both “function” and “admin” levels, they are using keys. What we need here is user-based authentication, hence we need to choose “anonymous” instead.

By default, new Functions have “function” as their authorization level.

After that, we need to turn on App Service Authentication under Platform Features of the Function.

Configuring platform features of the Function.

Besides that, we also need to specify “log in with Azure Active Directory” as the action to be taken when the request is not authenticate, as illustrated below.

Turning on App Service Authentication.

Then by clicking on the Azure AD which is listed as one of the Authentication Providers below the page, we can proceed to configure it. Here, we choose the Express mode as management mode. Then we can proceed to create a new Azure AD.

After this, the Azure AD will be labelled as “Configure (Express Mode: Create)”. We can then proceed to save the changes.

After the setting is saved, we can refresh the page and realizing the Azure AD is now labelled as “Configure (Express: Existing App)”. That means the Azure AD app has been created successfully.

The status of Azure AD for the Function is updated.

Now, click in to the Azure AD under the Authentication Providers list again. We will be brought to the section where we specified the management node earlier. Instead of choosing Express mode, now we can proceed to choose the Advanced mode.

We will then be shown with Client ID, Issuer Url, and Client Secret. According to Ben Martens’ advise, we have to add one more record, which is the domain URL of the Function, to the “Allowed Token Audiences” list to make Azure AD work with this Function, as shown in the following screenshot.

After making the change, we can proceed to save it.

What we need to do next is to create an Azure AD app for our client. To do so, we need to leave Azure Function page and head to Azure Active Directory page to add New Application Registration, as shown below.

Adding new application registration.

We then need to fill up a simple form to specify “Web app / API” as our Application Type and our Function URL as the Sign-on URL. Then we can click on the “Create” button and be brought to the page of the new app.

Next we need to give delegated permission for the client to access our Function with the steps highlighted in the following screenshot. Take note of the Application ID, we are going to use it later (Step A).

Giving permission.
Searching for the Function.

Then in the next step, we need to explicitly grant the access to the Function, as shown below.

Check the box to give delegated permission to access our Function.

After saving the changes, we also need to generate a key under the Azure AD, as shown in the following screenshot. Please note down the key in somewhere secured because it will only appear once (Step B).

Creating a never expired key.

Finally, in the Azure AD home page, we need to search for the app registration for the app that was created earlier in the Express mode for Function. Then we can retrieve the App ID URI which is a unique URL that Microsoft Azure AD can use for the app, as shown below (Step C).

Looking for the App ID URI.

Before we proceed to test our setup on Postman, we need to make sure we have the following:

Item 01 – tenantId: This is actually the Directory ID of our Azure AD.

Locating the Directory ID. (Image source: https://stackoverflow.com/a/41028320/1177328)

Item 02 – clientId: This is basically the Application ID that we got in Step A.

Item 03 – clientSecret: This is the key we generated in Step B.

Item 04 – resource: This is the App ID URI we found in Step C.

With these info, we then can proceed to create a new environment in Postman to try out.

Setting up the variables to be used in the environment.

After that, we will make a POST request to the following URL:
https://login.microsoftonline.com/{{tenantId}}/oauth2/token to retrieve the access token, as shown in the following screenshot.

This step is to get the access token.

With the access token now available, we then can make request to our Function, as shown below.

Yay, we can call the Function successfully.

If we don’t provide the bearer token, then we will not be able to access the Function. There will be an error message saying “You do not have permission to view this directory or page.”

Users with no correct credentials are blocked.

That’s all it takes to setup a simple authentication for Azure Function with Azure AD. If you find anything wrong above, feel free to correct me by leaving a message in the comment section. Thanks!

References

Advertisements

#azure, #azure-functions, #postman, #serverless-architecture

When WordPress Meets Azure SSL

In the afternoon, I received a message from my colleague in Marketing Team asking whether we could purchase an SSL certificate for the company blog which is powered by WordPress on Azure. There is almost no complete online tutorial on how to do this, hence I decided to write one.

Purchasing SSL Certificate and Binding it to Azure Web App

We can now easily purchase a SSL certificate from Azure Portal with less than USD 70 and enjoy auto renewal by default. By following the steps I documented on my Github page, we can easily bind the certificate to the WordPress site which is running as Azure Web App.

After that, we need to set the HTTPS Only option to be “On” so that all HTTP traffic will be redirected to HTTPS.

Updating WordPress Address and Site Address

After that, we need to proceed to the wp-admin to update the addresses. By default, for WordPress sites running as Azure Web Apps, the two fields, i.e. WordPress Address and Site Address, will be greyed out, as shown in the following screenshot.

We have no choice but to update HTTP to HTTPS in the URLs in the wp-config.php in wwwroot directory that we can download via FTP. The two lines that we need to update to use HTTPS are stated below.

//Relative URLs for swapping across app service deployment slots define('WP_HOME', 'https://'. filter_input(INPUT_SERVER, 'HTTP_HOST', FILTER_SANITIZE_STRING));
define('WP_SITEURL', 'https://'. filter_input(INPUT_SERVER, 'HTTP_HOST', FILTER_SANITIZE_STRING));

Updating wp-config.php

At this point of time, we will realize we can no longer enter the wp-admin web page. There will be saying our site is being redirected too many times or there is a redirect loop, as shown in the following image.

Oh no…

What we need to do, as recommended by thaevok on WordPress StackExchange, is we still need to add $_SERVER[‘HTTPS’] = ‘on’ as shown in the following code.

define('FORCE_SSL_ADMIN', true);
// in some setups HTTP_X_FORWARDED_PROTO might contain
// a comma-separated list e.g. http,https
// so check for https existence
if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)
$_SERVER['HTTPS']='on';

Yup, after doing all these, we have our blog secured.

Haulio blog is up!

#https, #php, #ssl, #wordpress

First Step into Orchard Core

This afternoon, I decided to take a look at Orchard Core, an open-source CMS (Content Management System) built on top of an ASP .NET Core application framework.

Since it is open-source, I easily forked its repository from Github and then checked out its dev branch.

After waiting for less than one minute to get all the Nuget packages restored in the project, I set OrchardCore.Cms.Web as the default project. Then I tried to run it but it failed with tons of errors. One of the major errors is “Assembly location for Razor SDK Tasks was not specified”. According to online discussion, it turns out that .NET Core 2.2 is needed.

After downloading the correct SDK, the projects are now successfully built with the following web page pops out as a result.

Take note that, as shown in the screenshot above, when I fill in Table Prefix, it will throw me exception saying that “SqlException: Invalid object name ‘OrchardroadDocument’” during the setup stage, as shown in the following screenshot.

Hence, the best way to proceed is to not enter anything to the Table Prefix textbox. Then we will be able to setup our CMS successfully. Once we log in to the system as Super User, we can proceed to configure the CMS.

Yup, this concludes my first attempt with the new Orchard Core CMS. =)

#cms, #open-source, #orchard, #technology

[KOSD Series] Increase Memory Allocated to PHP in Wordpress hosted on Microsoft Azure App Services on Linux

kosd-azure-app-service-filezilla-wordpress.png

“It became clear that we needed to support the Linux operating system, and we had already taken some rudimentary steps towards that with Azure.”

This is what Satya Nadella, Microsoft CEO, said in his book Hit Refresh. With the change he announced, today we can host a WordPress site easily on Microsoft Azure with the App Service on Linux option. Currently, my team has made use of this function on Azure to host our WordPress sites.

microsoft-loves-linux.png

Satya Nadella announcing the partnership. (Image Credit: The Verge)

This morning, I received a message from teammate with the following screenshot asking how to get rid of the following red messages.

memory-issues.png

Memory issues on WordPress!

This only happened after we installed a new theme called G5Theme for our WordPress site. The theme that we are using is called G5Plus Mowasalat.

So how do we approach this problem. Even though the three red lines are linked to the same “Increasing memory allocated to PHP“, there are fundamentally two places that we need to change.

Firstly, we need to add the following line to increase the WP_MEMORY_LIMIT to 128M in wp-config.php.

define('WP_MEMORY_LIMIT', '128M');
Released with WordPress 2.5, the WP_MEMORY_LIMIT option allows us to specify the maximum amount of memory that can be consumed by PHP.
The file is located under /site/wwwroot directory, as shown in the FTP screenshot below.

ftp-wp-config.png

This is where wp-config.php is located.

Changing this will only remove the first two red lines.

For the issue highlighted by the third red line, we need to update the max_input_vars value in .htaccess file which is located at the same directory with the following line.

php_value max_input_vars 3000

This max_input_vars is one of the PHP runtime configurations that is introduced since PHP 5.3.9 with default value of 1,000. What it means is simply the maximum number of input variables can be accepted in for example $_GET and $_POST.

Adding this will remove the final red line and everything will be shown green.

success

Hola! All are green.

KOSD, or Kopi-O Siew Dai, is a type of Singapore coffee that I enjoy. It is basically a cup of coffee with a little bit of sugar. This series is meant to blog about technical knowledge that I gained while having a small cup of Kopi-O Siew Dai.

Connecting Azure VM with Singtel Meg@POP

singtel-expressroute-vnet-virtualnetworkgateway-vm

Singtel Meg@POP IP VPN is a new service provided by Singtel, the largest mobile network operators in Singapore. According to its official website, it is designed for retail businesses with multi-sites and it can provide a more secure network as compared to Internet VPN. It leverages MPLS (Multi-Protocol Label Switching) technology, which bypasses the Internet and reduces exposure to cyberthreats.

One thing that I’d like to highlight here is that Singtel Meg@POP also offers connection to major cloud providers, such as Alibaba Cloud, Amazon Web Services, and Microsoft Azure, via their Cloud Gateway. Hence, if we have our services hosted on the cloud and our systems would like to talk to the applications running behind Singtel Meg@POP, we need to understand how to configure our cloud infrastructure to connect to the Singtel Meg@POP.

megapop-and-clouds.png

How Meg@POP works with the public clouds. (Source: Singtel Meg@POP)

In this article, I will be sharing my journey of setting up our VM on Microsoft Azure to link with Singtel Meg@POP via ExpressRoute.

Step 1: Subscribing ExpressRoute Service

Azure ExpressRoute is for us to create private connections between Azure datacentres and on-premise infrastructure. One good thing about ExpressRoute is that it does not go over the public Internet and thus it is able to offer a more reliable and faster Internet connection.

Hence, to connect with Singtel Meg@POP, Singtel staff recommended us to subscribe to the ExpressRoute on Microsoft Azure before they could provision the Meg@POP service.

It is better to consult with Singtel side before we proceed to subscribe ExpressRoute. In the first step of subscribing, we need to provide information such as Provider and Peering Location. After discussing with the friendly Singtel sales manager from the Business Segment, we managed to get the correct values to setup the ExpressRoute circuit.

setting-expressroute.png

Creating new ExpressRoute circuit on Azure Portal to connect to Singtel Meg@POP.

Step 2: Provisioning Meg@POP

Once the circuit is created successfully, we need to provide the Service Key of the circuit to Singtel staff. The Service Key can be found in the Overview section of the circuit, as shown in the screenshot below.

expressroute-service-key.png

Service Key of ExpressRoute circuit.

After we emailed the Service Key to Singtel, we needed to wait for them to provision Meg@POP. The whole process took about 21 days for our case. Finally we received a confirmation email from them saying that Singtel had commissioned the service and we could proceed to link our virtual network in Microsoft Azure to the ExpressRoute circuit.

Now, under the Peerings section of the ExpressRoute circuit, we shall see something as follows.

expressroute-peerings.png

Primary and secondary subnets are provisioned for Azure private peering.

Step 3: Creating Virtual Network on Azure

This is a step that we need to be careful. Before we proceed to create the VNet, we need to understand from the service provider that we are connecting to whether they only provision a certain subnet for us to use to connect.

For our case, the service provider that we are connecting to told us to use 10.10.1.0/24 subnet. Hence, when we are creating VNet, we need to use that as Address Space.

Also, please take note that the Address Range for the subnet that we are going to put our virtual machine in later needs to be smaller than the Address Space of the VNet specified above. Otherwise later we will not have address left for the Virtual Network Gateway. Hence, in our case, I choose 10.10.1.0/25.

creating-vnet.png

Creating VNet with a subnet having only 128 addresses.

Step 4: Creating Virtual Machine

Next, we proceed to create a new VM. In the Networking tab, we are required to configure VNet for the VM.

In this step, we need to choose the VNet and Subnet that we just created in Step 3. After that, for the convenience of direct RDP into the VM, we also need to set a Public IP and make sure Public inbound ports include RDP 3389 port

configuring-vnet-for-vm.png

Configuring the network interface of a VM.

Step 5: Opening Inbound and Outbound Ports

After the VM is setup successfully, we then need to proceed to configure the inbound and outbound port rules for the VM. This step is only necessary if we are asked to use certain ports to communicate with service hosted behind the Meg@POP.

This step can be easily done in the Network Security Group of the VM.

network-security-group-of-vm.png

Inbound and outbound security rules applied for a VM.

Step 6: Creating Virtual Network Gateway

We now need to create the Virtual Network Gateway with its subnet in one go.

A Virtual Network Gateway has two or more VMs which are deployed to the Gateway Subnet. The VMs are configured to contain routing tables and gateway services specific to the gateway. Thus, we are not allowed to directly configure the VMs and we are advised to never deployed additional resources to the Gateway Subnet.

There is one important step where we need to make sure we choose “ExpressRoute” as the Gateway Type, as shown in the screenshot below.

creating-virtual-network-gateway.png

Remember to choose ExpressRoute as the Gateway Type!

For the Gateway SKU, we are given three options: Standard, High Performance, Ultra Performance. As a start, we choose the Standard SKU which costs the least among three.

gateway-skus.png

Estimated performances by different gateway SKUs. (Source: Azure ExpressRoute)

Finally after choosing the VNet for the gateway, we will be prompted to specify the Address Range for the Gateway Subnet. In our case, I make it to be a bit smaller, which is 10.10.1.0/28.

Step 7: Creating Connection between ExpressRoute and VNet

Finally, we have to link up our VNet with the ExpressRoute.

To do so, we simply head to the Connections section of the ExpressRoute circuit to add the Virtual Network Gateway to it.

add-connection-to-expressroute-circuit.png

The table shows one connection successfully added to the circuit.

Conclusion

results.png

End results.

Yes, that’s all. This learning process took me about two weeks to learn. Hence, if you spot any mistakes in my article, please let me know. Thank you in advance.

If you would like to learn more about this, there is a very good tutorial video on Channel 9 about this too which they talk about Hybrid Networking! I learnt most of the knowledge from that tutorial video so I hope you find it useful as well. =)

Together, we learn faster!

TCP Listener on Microsoft Azure with Service Fabric

azure-service-fabric-load-balancer.png

Getting TCP listener to run on Microsoft Azure is always an interesting topic to work on. Previously, I did one experimental TCP listener on Azure Cloud Service and it works quite well.

Today, I’d like to share with you my another experiment which is hosting a TCP Listener on Microsoft Azure with Service Fabric.

Step 0: Installing Service Fabric SDK

Most of the time, it’s better to run the Visual Studio 2017 in Administrator mode otherwise debugging and deployment of Service Fabric applications may have errors.

Before we can start a new Service Fabric application project on Visual Studio, we first need to make sure Service Fabric SDK is installed.

service-fabric-sdk-must-be-installed.png

Visual Studio will prompt us to install Service Fabric SDK.

The template that I use is Stateless Service under .NET Core 2.0. This project template is to create a stateless reliable service with .NET Core.

Step 1: Add TCP Endpoint

In the ServiceManifest.xml of the PackageRoot folder of the application project, we need to specify an endpoint that our TCP Listener will be listening to. In my case, I am using port 9005. So I need to add an endpoint as shown below in the ServiceManifest.xml.

<Endpoint Name="TcpEndpoint" Protocol="tcp" Port="9005"/>

Step 2: Create Listeners

In the StatelessService class, there is a CreateServiceInstanceListeners method that we can override to create TCP listeners with the following codes.

protected override IEnumerable CreateServiceInstanceListeners()
{
    var endpoints = Context.CodePackageActivationContext.GetEndpoints()
        .Where(endpoint => endpoint.Protocol == EndpointProtocol.Tcp)
        .Select(endpoint => endpoint.Name);

    return endpoints.Select(endpoint => new ServiceInstanceListener(
        serviceContext => new TcpCommunicationListener(serviceContext, ServiceEventSource.Current, endpoint), endpoint));
}

Then in the RunAsync method, which is the main entry point for our service instance, we can simply include the code for TCP Listener to receive and send message to the clients.runasync.png

Step 3: Create Service Fabric Cluster

 

There are a few simple steps for us to follow in order to create a new Service Fabric cluster on Microsoft Azure.

Firstly, we need to specify some basic information, such as cluster name, OS, and default VM credentials.

service-fabric-step1-configure-basic-settings.png

Configure basic settings for a new Azure Service Fabric cluster.

Secondly, we need to define Node Types. Node types can be seen as equivalent to the roles in Cloud Service. Node types define the VM sizes, the number of VMs, and their properties. Every node type that is defined in a Service Fabric cluster maps to a virtual machine scale set.

We can start with only one node type. The portal will then prompt us to select one VM size. By default, it only shows three recommended sizes. If you would like to find out more other specs with lower price, please click on “View All”.

I once use A0 (which coasted USD 14.88) for experimental purpose. However, it turns out that the newly created service fabric cluster is totally not connectable with a status saying “Upgrade service unreachable”. The funny thing is that the status was only shown after everything in the resource group is setup successfully which strangely took about one hour plus to finish. So I wasted about one hour for that. Hence, please use at least the recommended size for the VM.

service-fabric-step2-configure-cluster.png

We need to specify the VM spec for each of the node type.

A very interesting point to take note is that, there is a checkbox for us to configure advance settings for node type, as shown in the following screenshot. The default values here will affect things such as the Service Fabric dashboard URL we use later. It’s fine to leave them as default.

service-fabric-step2-configure-cluster-advance-settings.png

Default values in the advanced settings of node type.

Thirdly, we need to configure the security settings by specifying which Key Vault to use. If you don’t have any suitable key vault, then it will take about one minute to create a new key vault for you. After the new key vault is created, you may be prompted with an error stopping you to proceed, as shown in the following screenshot.

service-fabric-step3-configure-security-settings-error.png

New key vault created here by default is not enabled for deployment.

To fix the error, we first need to visit the Key Vaults page. After that, we need to find out the key vault we just created above. Then we proceed to tick the corresponding checkbox to enable the key vault access to Azure VM for deployment, as shown in the following screenshot.

service-fabric-step3-configure-key-vault.png

Enable it so that Azure VM can retrieve certificates stored as secret from the key vault.

Now, if we got back to the Step 3 of the service fabric cluster setup, we can get rid of the error message by re-selecting the key vault. After keying a certificate name, we will need to wait for 30 seconds for validation. Then we will be given a link to download our certificate for later use.

service-fabric-step4-download-cert.png

Let’s download the cert from here!

This marks the end of our service fabric cluster setup. What we need to do is just to click on the “Create” button.

The creation process took about 40 minutes to complete. It actually went through many stages which are better described in the article “Azure Service Fabric Cluster – Deployment Issues”, written by Cosmin Muscalu.

Step 4: Publish App from Visual Studio

After the service fabric cluster is done, we can proceed to publish our application to it.

In the Solution Explorer, we simply need to right-click on the Service Fabric project and choose Publish, as shown in the following image.

solution-explorer

Solution Explorer

A window will popup and prompt us that the Connection Endpoint is not valid, as shown below.

cannot-publish-to-server.png

Failed to connect to server and thus we cannot publish the app to Azure.

Now, according to the article from the link “How to configure secure connection”, we have to install the certificate that we downloaded earlier from Azure Portal in Step 2.

Since there is no password for the pfx file, we simply need to accept all default settings while importing the certificate.

Now if we go back to the Publish window, we will see a green tick icon appearing at the side of the Connection Endpoint. Now, we are good to proceed to do a publish. The deployment of a simple TCP Listener normally takes less than one minute to finish.

Step 5: Open Port Access

After the deployment is done, we need to open up the 9005 port that we specified above in Step 2. To do so, we need to visit the Load Balancer used by the service fabric cluster to add a new rule for the port 9005 to be accessible from public.

add-load-balancing-rule.png

Add a new load balancing rule for the service fabric.

The process of adding a new rule normally takes about three minutes to complete.

Please take note that we need to note down the Public IP Address of our load balancer as well.

load-balancer-public-ip-address.png

The Public IP Address of a load balancer can be found in its Overview panel.

Step 6: Open Up Service Fabric Explorer

Finally, we need to open up the Explorer for our service fabric cluster. To do so, we can retrieve the dashboard URL in the Overview panel of the service fabric cluster.

service-fabric-admin-dashboard.png

The Service Fabric Explorer URL is here.

To access the Explorer, we first need to select a certificate that we downloaded earlier to authenticate ourselves to the Explorer, as shown in the screenshot below.

select-certificate.png

Selecting a certificate on Google Chrome.

Step 7: Communicate with TCP Listener

Now, if we build a simple TCP client to talk to the server at the IP address of the load balancer that we noted down earlier, we can easily send and receive response from the server, as shown in the screenshot below.

tcp-client.png

Hooray, we receive the response from the application on Azure Service Fabric!

So yup, that’s all for a very simple TCP Listener which is hosted on Microsoft Azure.

I will continue to research more about this topic with my teammates so that I can find out more about this cool technology.

Protecting Web API with User Password

identity-server

In my previous post, I shared about the way to connect Android app with IdentityServer4 using AppAuth for Android. However, that way will popup a login page on a web browser on phone when users are trying to login to our app. This may not be what the business people want. Sometimes, they are looking for a customized native login page on the app itself.

To do so, we can continue to make use of IdentityServer4.

IdentityServer4 has a grant which is called Resource Owner Password Grant. It allows a client to send username and password to the token service and get an access token back that represents that user. Generally speaking, it is not really recommended to use the AppAuth way. However, since the mobile app is built by our own team, so using the resource owner password grant is okay.

Identity Server Setup: Adding New API Resource

In this setup, I will be using in-memory configuration.

As a start, I need to introduce a new ApiResource with the following codes in the Startup.cs of our IdentityServer project.

var availableResources = new List<ApiResource>();
...
availableResources.Add(new ApiResource("mobile-app-api", "Mobile App API Main Scope"));
...
services.AddIdentityServer()
    ...
    .AddInMemoryApiResources(availableResources)
    .AddInMemoryClients(new ClientStore(Configuration).GetClients())
    .AddAspNetIdentity<ApplicationUser>();

Identity Server Setup: Defining New Client

As the code above shows, there is a ClientStore that we need to add a new client to with the following codes.

public class ClientStore : IClientStore
{
    ...

    public IEnumerable<Client> GetClients()
    {
        var availableClients = new List<Client>();
        
        ...
        
        availableClients.Add(new Client
        {
            ClientId = "mobile-app-api",
            ClientName = "Mobile App APIs",
            AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
            ClientSecrets = { new Secret(Configuration["MobileAppApi:ClientSecret"].Sha256()) },
            AllowedScopes = { "mobile-app-api" }
        });

        return availableClients;
    }
}

Configuring Services in Web API

In the Startup.cs of our Web API project, we need to update it as follows.

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

    services.AddAuthorization();

    services.AddAuthentication("Bearer")
    .AddIdentityServerAuthentication(options =>
    {
        options.Authority = "<URL of the identity server>";
        options.RequireHttpsMetadata = true;
        options.ApiName = "mobile-app-api";
    });

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

Configuring HTTP Request Pipeline in Web API

Besides the step above, we also need to make sure the following one line “app.UseAuthentication()” in the Startup.cs. Without this, we cannot make the authentication and authorization to work in our Web API project.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ...
    app.UseAuthentication();
    app.UseMvc();
}

Receiving Username and Password to Return Access Token

We also need to add a new controller to receive username and password which will in return tell the mobile app whether the login of the user is successful or not. If the user is logged in successfully, then an access token will be returned.

[Route("api/[controller]")]
public class AuthenticateController : Controller
{
    ...
    [HttpPost]
    [Route("login")]
    public async Task<ActionResult> Login([FromBody] string userName, string password)
    {
        var disco = await DiscoveryClient.GetAsync("<URL of the identity server>");
        var tokenClient = new TokenClient(disco.TokenEndpoint, "mobile-app-api", Configuration["MobileAppApi:ClientSecret"]);
        var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(userName, password, "mobile-app-api");

        if (tokenResponse.IsError)
        {
            return Unauthorized();
        }

        return new JsonResult(tokenResponse.Json);
    }
    ...
}

Securing our APIs

We can now proceed to protect our Web APIs with [Authorize] attribute. In the code below, I also try to return the available claims via the API. The claims will tell the Web API who is logging in and calling the API now via the mobile app.

[HttpGet]
[Authorize]
public IEnumerable<string> Get()
{
    var claimTypesAndValues = new List<string>();

    foreach (var claim in User.Claims)
    {
        claimTypesAndValues.Add($"{ claim.Type }: { claim.Value }");
    }

    return claimTypesAndValues.ToArray();
}

Conclusion

This project took me two days to find out how to make the authentication works because I misunderstand how IdentityServer4 works in this case. Hence, it is always important to fully understand the things on your hands before working on them.

do-not-give-up.png

Do not give up! (Source: A Good Librarian Like a Good Shepherd)

Reference

#asp-net-core, #c, #identityserver, #microsoft, #openid, #programming, #technology, #web-api