FreePascal REST API’s — Authenticating requests with Basic Auth

Marcus Fernström
5 min readMay 27, 2020

--

Before your REST API performs actions for a user, it’s a good idea to authenticate the request.

There are several ways to authenticate API requests. The one we’ll be talking about today is called Basic Auth.

Basic Auth is a tried-and-true method for passing authentication information with a request used for both websites and REST API’s.

It’s very easy to use, it’s just a Base-64 encoded value in the Authorization header.

Just remember that while the authentication payload is encoded, it’s not encrypted.

Always use HTTPS/SSL if at all possible to protect against MITM attacks.

Using Basic Auth is very easy.

In the Authorization header you need to place the value Basic username:password and the username:password part needs to be base64 encoded.

Here’s an example. let’s say you have the username bob and a password bobiscool

You base-64 encode the value bob:bobiscool which gives you Ym9iOmJvYmlzY29vbA==

Now add that to the Authorization header, specifying that we’re using Basic authentication.

Authorization: Basic Ym9iOmJvYmlzY29vbA==

To encode and decode base64 strings in FreePascal/Lazarus, use the SimpleBaseLib, you can find it in the OPM (Online Package Manager) under Meny -> Package -> Online Package Manager

Add base64 to your uses section and you’re ready to go.

The process for implementing Basic Auth in an API is straight forward

  • Check if there’s a value in the Authorization header
  • Make sure the first word says Basic
  • Base-64 Decode the second word
  • Grab the username and password from the decoded value
  • Do whatever validation your app needs

I’ve created a template for Basic Auth REST endpoints, you can find it on GitHub.

Here’s the template for Basic Authentication

{
Where https://github.com/MFernstrom/rest-api-templates
What Basic Auth template
Who Marcus Fernström
License Apache 2.0
Version 1.0
}
program BasicAuthTemplate;{$mode objfpc}{$H+}uses
{$IFDEF UNIX}cthreads,
cmem, {$ENDIF}
SysUtils,
strutils,
fphttpapp,
httpdefs,
httproute,
fpjson,
base64;
procedure validateRequest(aRequest: TRequest);
var
headerValue, b64decoded, username, password: string;
begin
headerValue := aRequest.Authorization;
if length(headerValue) = 0 then
raise Exception.Create('This endpoint requires authentication');
if ExtractWord(1, headerValue, [' ']) <> 'Basic' then
raise Exception.Create('Only Basic Authentication is supported');
b64decoded := DecodeStringBase64(ExtractWord(2, headerValue, [' ']));
username := ExtractWord(1, b64decoded, [':']);
password := ExtractWord(2, b64decoded, [':']);
// Replace this with your own logic
if (username <> 'marcus') or (password <> '112233') then
raise Exception.Create('Invalid API credentials');
end;
procedure jsonResponse(aResponse: TResponse; JSON: TJSONObject; httpCode: integer);
begin
aResponse.Content := JSON.AsJSON;
aResponse.Code := httpCode;
aResponse.ContentType := 'application/json';
aResponse.ContentLength := length(aResponse.Content);
aResponse.SendContent;
end;
procedure apiEndpoint(aRequest: TRequest; aResponse: TResponse);
var
JSON: TJSONObject;
httpCode: integer;
begin
JSON := TJSONObject.Create;

try
try
validateRequest(aRequest);
JSON.Add('success', True);
JSON.Add('time', DateToStr(now));
httpCode := 200;
except
on E: Exception do
begin
JSON.Add('success', False);
JSON.Add('reason', E.message);
httpCode := 401;
end;
end;
jsonResponse(aResponse, JSON, httpCode);
finally
JSON.Free;
end;
end;
begin
HTTPRouter.RegisterRoute('/api', @apiEndpoint);
Application.Port := 9080;
Application.Threaded := True;
Application.Initialize;
WriteLn(format('API is ready at http://localhost:%d/', [Application.Port]));
Application.Run;
end.

Go ahead and copy the code into the Lazarus IDE, Medium isn’t the greatest place for reading source code.

We have three procedures in this template.

  • jsonResponse
  • validateRequest
  • apiEndpoint

jsonResponse

This procedure has a single purpose, to take a JSONObject and create a response to the request. It’s not all that helpful when we only have one endpoint, but when you have several endpoints it’s a good way to stay DRY (Don’t Repeat Yourself).

validateRequest

The validateRequest procedure is where we do the validation of the the authorization credentials.

We use a simple pattern of throwing errors with custom messages if anything goes wrong or the validation fails.

We check to make sure the authorization header is present, has a value, and is set to Basic before we check the username and password at the end

if (username <> 'marcus') or (password <> '112233') then
raise Exception.Create('Invalid API credentials');

This is where you implement your check to see if the credentials are valid or not.

Remember to hash the password when storing it.

apiEndpoint

This procedure gets invoked when a user makes a request for the /api path, set in HTTPRouter.RegisterRoute

We wrap the invocation of validateRequest in a try/except and if there’s an error we respond with a 401 (HTTP code for an unauthorized request).

If there’s no error, we know that validation passed so we carry on with the request.

In this template endpoint we add the current time to the TJSONObject and respond with http code 200 (Ok).

Output

Using the Insomnia desktop tool it’s really easy to test endpoint.

Here I’m hitting it without passing any authorization details

It’s a little hard to read. Let’s just look at the responses on the right-hand side.

If we don’t pass in any authorization details at all, we see this

And if we pass credentials but they’re incorrect, our endpoint lets us know.

And finally, if we pass in the correct credentials, we get a 200 response with the current time.

That’s all there is to using Basic Auth in FreePascal. Feel free to use the template as a starting point.

If you like my articles, give it a Clap and a Share, it really helps me out.

If you have questions, ideas, or feedback, connect with me on LinkedIn.

--

--

Marcus Fernström

Sr. AppSec Engineer and Software Developer with a passion for open source. Historical Fencing instructor, and drinker of copious amounts of coffee and tea.