SecureAuth API: Creating the Go SDK

csa_background
Back to Blog
December 13, 2016
Jeff Hickman

 

Background

At SecureAuth, we are committed to providing world class strong authentication, with adaptive capabilities, in as many diverse integrations as possible. SecureAuth is dedicated to providing modern, well vetted, and easy to implement Software Development Kits (SDKs) for some of the largest programming languages in wide use at all organizations. With this mission in mind, I was offered the opportunity to help build an SDK for a modern language that we have fallen in love with at SecureAuth: Go (AKA: golang).

Go: A Little History

Go is a programing language developed at Google in 2007 by Robert Griesermer, Rob Pike, and Ken Thompson. It was created to address the large scale, concurrent services that Google was struggling to control with other well-known programming languages. Google quickly realized that Go had a much wider application outside of their own use, and announced in 2009 that Go would be free and open source for wider use. This allows any organization, enterprise, or hobbyist to build services, programs, web applications in Go by simply downloading and using the provided tools. In fact, some of the most disruptive technology to come out in recent years, utilize Go in their application set, such as Docker, CloudFlare, DropBox, Netflix, among others.

At its root, Go is a C derived language that compiles down to machine code, which makes it fast to compile and easy to use cross-platform. Go is a fast, statically typed, opinionated language, with the goal of making code that is easy to read, fast to develop, and require minimal cooperation between developers to make complete programs. With these features in mind, SecureAuth realized the immediate benefit and knew that our customers would as well.

SDK Design
Client

Building a SDK in a language such as Go is a bit of a challenge as the language is still very new (in relative terms) and some documentation can be hard to track down to provide specific functionality. This is also the beauty of the language, there is flexibility in how you implement features and choose to structure your code. The immediate goal with the Go SDK was to provide the tools needed to build the authentication headers that the SecureAuth API set uses to authenticate a program to use the APIs. The Go SDK for SecureAuth APIs offers a client package that provides the function to sign, build, and “Do” RESTful API requests. Provided in the client package is a “helper” function that makes it easy to instantiate a new Client struct, NewClient(). Here is a look at that function:

func NewClient(appId string, appKey string, host string, port int, realm string, ssl bool, bypassCert bool) (*Client, error) {

       params := []string{appId,appKey,host,realm}

       for _, v := range params {

              if isNil(v) {

                     return nil, errors.New(fmt.Sprintf("%v is required to create a new client.", v))

              }

       }

       c := new(Client)

       c.AppId = appId

       c.AppKey = appKey

       c.Host = host

       if port == 0 {

              c.Port = 443

       } else {

              c.Port = port

       }

       c.Realm = realm

       c.SSL = ssl

       c.BypassCertValidation = bypassCert

       return c, nil

}
 

As you can see, this function takes the needed information to build a request to the SecureAuth APIs and gives you a data structure that allows you to re-use the information to complete various extension functions provided, such as sign requests and build Get-Post-Put requests.

Modularity

The next design goal in mind was to make the SDK modular. This was easy to do with Go; We simply made each endpoint or functionality of the SecureAuth API a package in a service directory. This means that, using the source of the SDK, you can choose to include only the features you need. This allows a developer to keep the size and dependency footprint of a project small and manageable. Each of the service packages do require the Client data struct to execute requests, but the inverse is not true. The Client package can be the only package a developer uses and they can choose to implement their own functions, packages, or features to use SecureAuth APIs.

Helpers

Once the modularity of the design was completed, We were presented with a unique choice in how far we took the SDK to make things easier for a developer. Traditionally, Go encourages developers to implement their own code to handle the problem they are solving. We could have left each of the packages with just the required data structures, yet in our opinion any good SDK provides end to end functionality. With that self-imposed requirement, We added functions to each package to abstract away the need for any developer implementing the SDK to build their own logic for handling each API endpoint. For example:

func (r *Request) SendCallOtp(c *sa.Client, userId string, factorId string)(*Response, error){

       r.UserId = userId

       r.ReqType = "call"

       r.FactorId = factorId

       callResponse, err := r.Post(c)

       if err != nil {

              return nil, err

       }

       return callResponse, nil

}

In the example above, We created an extension method that allows the easy sending of a Voice Call to a user’s telephone number. A developer needs to provide the function parameters to complete the API call. However, We believe in choice and the cornerstone of any good SDK allows many ways for a developer to implement the framework. To this end, developers could choose to build a Request data struct, provide the needed data for the request type they want, and call the Get, Post, or Put function in the package to complete the API request. For example:

func (r *Request) Get(c *sa.Client, refId string)(*Response, error) {

       endpoint := buildEndpointPath(refId)

       httpRequest, err := c.BuildGetRequest(endpoint)

       if err != nil {

              return nil, err

       }

       httpResponse, err := c.Do(httpRequest)

       if err != nil {

              return nil, err

       }

       authResponse := new(Response)

       if err := json.NewDecoder(httpResponse.Body).Decode(authResponse); err != nil{

              return nil, err

       }

       authResponse.HttpResponse = httpResponse

       httpResponse.Body.Close()

       return authResponse, nil

}
Concurrency

One feature that We would like to highlight in Go is the built in support for concurrency. Concurrency allows developers to build applications that can run functions or complete packages in something called a goroutine. This allows multiple functions to be ran at the same time, without waiting for a result or response from the function. This is extremely useful in web servers that may be handling multiple requests at once and need to be responsive to each user and what they are doing in the application. We found a good spot to use this functionality in the SDK: Push to Accept reference checking. In the SecureAuth API when you send a Push to Accept two-factor method to a user’s device, a reference id is returned. This reference id is then used to make Get requests against an endpoint to poll for when a user has accepted, denied, or ignored the login request. Putting this reference check into a channel (or goroutine) lets the developer handle other logic while we wait for the user’s response. Here is that bit of code:

func (r *Request) CheckPushAcceptStatus(c *sa.Client, refId string, timeout int, interval int)(*Response, error) {

       tout := time.After(time.Duration(timeout) * time.Second)

       tick := time.Tick(time.Duration(interval) * time.Second)

       for {

              select {

              case <- tout:

                     return nil, errors.New("Request expired before response.")

              case <- tick:

                     checkResponse, err := r.Get(c, refId)

                     if err!= nil {

                            return nil, err

                     }

                     switch checkResponse.Message {

                     case "ACCEPTED", "DENIED", "FAILED", "EXPIRED":

                            return checkResponse, nil

                     case "PENDING":

                            continue

                     }

              }



       }

}

Now, this is a bit blocking from a code perspective, because we need the user response before we allow the authentication to proceed. However, placing this check into a channel allows the check to run in a much more responsive manner (overlaying requests before the previous one finished) and gives a better user experience (in our tests it was almost instant from when we pressed accept in our app) for accepting or denying Push to Accept.

Error Handling

The last code focused facet of this blog post revolves around a design feature of Go: errors and error handling. Traditionally, most programming languages provide a language syntax for handling errors, such as the try…catch pattern. With Go, errors are intended to be handled by the implementer and no such syntax is provided; We consider this a strength of the language. It gives the developers the ability to quickly prototype projects, build custom error logic, and due to the nature of multiple returns on functions, forces proper error handling. In the Go SDK for SecureAuth, each function has at least two returns, first is the expected struct or variable, then any error that was encountered. It is the developer’s job to properly handle these errors and build logic for what will happen in their application when an error is encountered.

Wrap Up

We hope that this SDK helps developers create innovative, modern, and secure applications with strong authentication! By the way, it is all open source! It can be found on GitHub at: https://github.com/SecureAuthCorp/saidp-sdk-go. If you have ideas for feature improvements, changes, enhancements, or bug fixes, feel free to fork, branch, and pull. Each change will be reviewed, tested and, if valid, added to the core SDK.

Visit our SecureAuth IdP solutions page to learn more about our on-premises solutions. Or visit our cloud-based single sign-on authentication solution page to learn more on how you can determine identities with confidence via a cloud-based solution.

 

Never Miss a Beat
Subscribe to Our Blog

SecureAuth Identity Platform Adaptative Authentication

Identity and Access Management

Empower your digital initiatives with secure access for everyone and everything connecting to your business

Product Features

Adaptive Authentication

Extend verification of a user identity with contextual risk checks

Multi-Factor Authentication

Leverage a broad portfolio of authentication factors for desktop and mobile

Intelligent Risk Engine

Protect your identities with advanced risk profiling analytics

Single Sign-On

Provide app discovery and one-click login through portal or desktop SSO

User Lifecycle Management

Enable admins with strong CRUD capabilities and users with self-service tools

Secure All Identities

CIAM

Customer Identities

Deliver a frictionless customer experience safeguarding user data and privacy

B2E

Workforce Identities

Govern and control access rights for employees, partners, and contractors

SecureAuth Authenticate App

Passwordless MFA client with
Symbol-to-Accept. Stronger security.

The Value of Deploying Multi-Factor Authentication in a Digital World

Value of Deploying Multi-Factor Authentication in a Digital World

Read this white paper to gain insights and understanding of why passwords create risk and blind spots for organizations and their users.

Initiatives

Passwordless Authentication

Reduce the risk of breaches by eliminating passwords

2FA is Not Enough

Block popular phishing and brute force attacks used by bad actors

Protecting Office 365

Extend adaptive authentication and flexible MFA to all apps including Office 365

Securing Portals and Web Apps

Balance strong security and an exceptional user experience

RSA Migration

Transition to a modern identity and access management solution

Industries

Healthcare

Financial Services

Retail

Energy and Utilities

Public Sector

Resources

White Papers

eBooks

Analyst Reports

Documentation

Events

Recorded Webinars

Innovation Labs

Support Portal

Calculate Your Savings

Lower support costs by enabling your users the control to reset passwords, account unlocks, device enrollment and update profiles

Meet SecureAuth

About SecureAuth

Careers

Contact