Developing protected Serverless Web Applications

Serverless platforms are often used to build APIs for web and mobile apps. I’ve open sourced a pattern that shows how to implement protected APIs with IBM Cloud Functions and how to invoke them from Angular web applications.

Get the code from GitHub.

IBM Cloud Functions comes with an API Gateway. Developers can grant access to their APIs via application keys and they can track usage via graphical dashboards. For user authentication Google, Facebook and GitHub accounts can be used via OAuth.

serverless-webapp (1)

The static resources of web applications can be hosted in various ways, for example on GitHub pages. Since the JavaScript files are loaded in browsers, for security reasons they must not include the credentials to access the APIs. Instead OAuth is used to authenticate users before invoking the protected APIs. Read the documentation for more information.

The following diagram describes the flow of authenticating and authorizing a user in the sample application:


  1. User opens the Angular web application via web browser and clicks the ‘login’ button.
  2. Web application opens the Google OAuth web page, where users authenticate and grant the application access.
  3. Google page redirects to OpenWhisk sequence ‘oauth-login-and-redirect’ with a code parameter in the URL.
  4. The sequence is triggered. The first OpenWhisk function ‘oauth-login’ reads the code and invokes a Google API endpoint to exchange the code against a token.
  5. The same ‘oauth-login’ function invokes with the token another Google API endpoint to read user profile information, such as the user name.
  6. The sequence invokes the next OpenWhisk function redirect, which invokes the Angular app with the token and the user name in the URL.
  7. When users click on the ‘invoke protected action’ button in the Angular app, a REST API to the API management is invoked. The request contains the token.
  8. API management validates the token. If valid, the OpenWhisk function protected-action is invoked. If the token is invalid, the request will be rejected and response code 401 will be returned.
  9. The response from ‘protected-action’ is displayed in the Angular application.

This is the code of step (4) which reads the access token. The OAuth client id and secret are only accessible in this code and not in the client side JavaScript code.

function main(params) {
   return new Promise((resolve, reject) => {
      const providers = params.providers;
      const code = params.code;
      var providerName = params.provider || params.providerName;
      var provider = providers[providerName];
      var form = {
         client_id: provider.credentials.client_id,
         client_secret: provider.credentials.client_secret,
         code: code
      var options = {
         url: provider.endpoints.token,
         method: 'POST',
         headers: {
            'Content-Type': 'application/json'
      request(options, function (err, response, body) {
         if (err || response.statusCode >= 400) {
         } else {
            body = JSON.parse(body);
            var accessToken = body.access_token;

Thanks a lot to my colleague Andy Shi who converted this sample into a code pattern.

If you want to try out OpenWhisk in the cloud, you can get an account on the IBM Cloud.