b2b API Authentication

b2b API Authentication

·

4 min read

Let's say we have a company and we have some partnerships or integrations with some other companies. And we want to allow some requests that come from them to do some things on our side. How can we do that securely?

We will focus on that in this article.

Don't forget, this scenario is working as b2b, so there will be no login page. Also, probably, these requests will come to us automatically and will be triggered by some services on the consumer side. So there won't be any page.

Techstack

We'll be using .NET 6 framework, C# language, Minimal API template, Dapper ORM, Swagger, and SQLite. And we'll use Postman for testing.

Actually, we have some similar samples for understanding the concept.

When you sign in to a platform as a developer, these platforms give you some access tokens, and you can use these to do some things on these platforms. So, yes, we'll give a token to our API consumer, and other requests will work with this token.

There are some other approaches, but this is not bad either. This approach is working and very easy to apply, and you don't need to use any third-party solution.

Let's get started, and try to understand the concept while developing our project.

I'm using Visual Studio for the Mac, but the steps are almost the same for the Windows os.

We are starting with choosing our template.

1.png 2.png

Please uncheck the Use Controllers for using the Minimal API template.

This is sufficient for our project. And we'll only change the Program.cs file's content.

4.png

Now we can start coding.

var connectionString = builder.Configuration.GetConnectionString("b2bAPIDB") ?? "Data Source=b2bAPI.db;Cache=Shared";
var sharedSaltKey = builder.Configuration.GetSection("AppSettings:SharedSaltKey").Get<string>() ?? "SHAREDSALTKEY";

builder.Services.AddScoped(_ => new SqliteConnection(connectionString));

We are setting our connection string and salt key for security. We will talk about the salt key later. And we are injecting our database connection.

The codes are very simple, and you can look at the Github repo.

github.com/canurek/b2bAPIAuth

We have just 3 endpoints in this API.

app.MapGet("/", () => "Hello World!")

app.MapPost("/gettoken", async ([FromBody] GetTokenModel model, SqliteConnection db) =>

app.MapPost("/oursecurejob", async (string tokenString, SqliteConnection db) =>

Now we'll talk about the "/gettoken"

This is our GetTokenModel class.

class GetTokenModel
{
    public string? UserName { get; set; }
    public string? Password { get; set; }
    public string? ProcessDate { get; set; }
    public string? Signature { get; set; }

    public override string ToString()
    {
        return string.Concat(UserName, Password, ProcessDate);
    }
}

Our API consumer will come to us with this.

6.png

I set the ProcessDate variable in the following format. yyyyMMddHHmmss

For example => 20211208010203

We have to share this info with our API consumer, and we have to give a formula for creation signature data.

The consumer has to create this data by concatenating these variables in order. And the result should be hashed with md5.

MD5(username+password+processdate+SHAREDSALTKEY)

We are using the process date in the formula to generate dynamic data for each request. And we are using the SHAREDSALTKEY variable for extra security.

You can get information about encryption, hashing, and salting at this link.

thesslstore.com/blog/difference-encryption-..

As you can see, testing this scenario with Swagger is really hard. Because we'll need to recreate our signature data for each request, so we'll use Postman for that.

Our root URL just gives us a "Hello World" message.

7.png

And now, we are trying to get a token.

8.png

We got an error because we didn't calculate the signature. At this point, we'll use the "Pre-request script" tab in Postman.

We'll change the Request Body like that.

{
  "userName": "canurek",
  "password": "123456",
  "processDate": "{{processDate}}",
  "signature": "{{signature}}"
}

And, this will be our pre-request script content. This script will provide us to change the processDate and signature variables dynamically for each request.

var requestToUpdate = pm.request.body.toString();
const moment = require('moment');
postman.setEnvironmentVariable('processDate', 
moment().format("YYYYMMDDHHmmss"));

var reqBody = JSON.parse(request.data);

var concat = reqBody.userName +
    reqBody.password + 
    pm.variables.get('processDate') +
    'SHAREDSALTKEY';

console.log(concat);

var signature = CryptoJS.MD5(concat).toString().toUpperCase();

postman.setEnvironmentVariable('signature', signature);

var elementsToReplace = requestToUpdate.match(/{{.+}}/g);

var updatedRequest = requestToUpdate;

elementsToReplace.forEach(function(entry) {
    var variableName = entry.replace("{{", "").replace("}}", "");
    updatedRequest = updatedRequest.replace(entry, 
pm.variables.get(variableName));
});

So, we get a token successfully.

9.png

Then, we can use this token.

10.png

You can change the passing method of the token. I just used query string.

I hope this article will be useful and informative for someone.

Github Repo
github.com/canurek/b2bAPIAuth

References
docs.microsoft.com/en-us/aspnet/core/tutori..