A very important part of creating REST APIs is authentication.

We need the ability to sedure API endpoints for different callers.

Some endpoints are unsecured and can be called anonymously while most other endpoints will require some form of authentication.

There are several methods for authentication in use for REST services.

  • BASIC
  • BEARER
  • JWT
  • OATUH

in addition to the type of authentication we also want to be able to secure different API routes with different methods and for different API users.

Our REST library implements authentication on a per route basis but also allows definition per controller.

It also allows multiple types of authentication for the same route. 

One route could have BASIC authentication as well as BEARER authentication at the same time. 

For example a good practice is to require authentication on the controller which automatically forces all routes of a controller to require authentication.

Then, if a route is added that requires anonymous access we can override the authentication on that route only.

 

so to start we will create a new API controller as follows

Object oAuthSampleAPI is a cszWebAPIController
    // The psPath property determines the path in the URL for which requests will be handled.
    Set psPath to "api/v1/authsample"
    // Use psVerbs to filter based on the HTTP Verbs. 
    Set psVerbs to "*"
Procedure ManualGet Integer hoJson Get Create (RefClass(cJsonObject)) to hoJson Send InitializeJsonType of hoJson jsonTypeObject Send SetMemberValue to hoJson "timestamp" jsonTypeString (ConvertToClient(typeDateTime, CurrentDateTime())) Send SetMemberValue to hoJson "message" jsonTypeString "You can see this message" Send OutputJson hoJson Send Destroy to hoJson End_Procedure Send RegisterPath "GET" "" (RefProc(ManualGet)) Set pbPathScalar to True Set psPathSummary to "Manual API function" End_Object

a very simple controller actually the same as the manual api we built earlier. At this time there is no authentication so we should be able to call the GET method and it will return the HTTP code 200 and the data.

 

to secure our API we can tell the controller that authentication is required by setting the following property

Set pbAuthRequired to True

running the API now will produce an error 401 and the controller will no longer return any data.

lets see how we can BASIC authentication that will work for the whole controller

first we need to enable BASIC authentication on the controller

 Send AddAuth "BASIC"

now that BASIC authentication is enabled we need to validate credentials as they are used.

For BASIC authentication we implement the following event

Function OnValidateAuthBasic String sVerb String sPath tWebAPIPath path String sUser String sPassword Returns Boolean
    If (sUser="mike" and sPassword="austrianthunder") Begin
        Function_Return True
    End
End_Function

what if we have a route in our controller that should allow anonymous access. As mentioned earlier it is always safer to force the full controller to authenticate and then override specific functions.

Lets define a sample route with anonymous access

 Send RegisterPathAuth "GET" "/anon" (RefProc(ManualGet)) WEPAPI_AUTHMODE_ANONYMOUS 
 Set pbPathScalar to True
 Set psPathSummary to "Manual API function no auth"

this will register the path /anon with anonymous access.

We can also declare a specific path with a specific type of authentication. For example for BASIC authentication

 Send RegisterPathAuth "GET" "/basic" (RefProc(ManualGet)) WEPAPI_AUTHMODE_REQUIRED "BASIC"
 Set pbPathScalar to True
 Set psPathSummary to "Manual API basic auth only"

or for both BASIC and BEARER authentication

 // register path with BASIC and BEARER auth
 Send RegisterPathAuth "GET" "/bandb" (RefProc(ManualGet)) WEPAPI_AUTHMODE_REQUIRED "BASIC"
 Send AddPathAuth "BEARER"
 Set pbPathScalar to True
 Set psPathSummary to "Manual API basic and bearer auth"

in our sample application we also added a simple database table to add users to authenticate the web APIs

the code to validate BASIC authentication looks as follows

Function OnValidateAuthBasic String sVerb String sPath tWebAPIPath path String sUser String sPassword Returns Boolean
    Clear WEBAUTH
    Move “BASIC” to WEBAUTH.TYPE
    Move sVerb to WEBAUTH.VERB
    Move path.sPath to WEBAUTH.PATH
    Move sUser to WEBAUTH.TOKEN
    Find EQ WEBAUTH by Index.1
    If (Found) Begin
        If (WEBAUTH.PASSWORD=sPassword) Function_Return True
    End

End_Function

 

Michael Salzlechner is the CEO of StarZen Technologies, Inc.

He was part of the Windows Team at Data Access Worldwide that created the DataFlex for Windows Product before joining StarZen Technologies. StarZen Technologies provides consulting services as well as custom Application development and third party products