Authorization Flow Authentication

Last updated: 2021-12-17 Contributors Byrne ReesePaco Vu
Edit this page

Welcome to the RingCentral Platform. RingCentral is the leading unified communications platform. From one system developers can integrate with, or build products around all the ways people communicate today: SMS, voice, fax, chat and meetings.

In this Quick Start, we are going to help you authorize a user to login with username and password to get an access token and a refresh token. Let's get started.

Create an App

The first thing we need to do is create an app in the RingCentral Developer Portal. This can be done quickly by clicking the "Create User Login App" button below. Enter a name and description if you want to change them, and click the "Create" button. If you do not yet have a RingCentral account, you will be prompted to create one.

Create User Login App

  1. Login or create an account if you have not done so already.
  2. Go to Console/Apps and click 'Create App' button.
  3. Select "REST API App" under "What type of app are you creating?" Click "Next."
  4. Under "Authentication" select "3-legged OAuth flow authorization code" and then "Server-side web app."
  5. Under "Authentication" specify the redirect Uri as http://localhost:5000/oauth2callback.
  6. Under "Security" add the following permissions:
    • ReadAccounts
    • ReadCallLog
  7. Under "Security" select "This app is private and will only be callable using credentials from the same RingCentral account."

When you are done, you will be taken to the app's dashboard. Make note of the Client ID and Client Secret. We will be using those momentarily.

Download and edit a .env file

Follow the instructions found in our guide to running Developer Guide code samples. Or:

  1. Download our env-template and save it as a file named .env.
  2. Edit your newly downloaded .env file, setting its variables with the proper values for the app you created above.

Authorization Flow

Select your preferred language below.

Install RingCentral JavaScript SDK and some dependencies

$ npm install @ringcentral/sdk --save
$ npm install dotenv --save
$ npm install express --save
$ npm install express-session --save
$ npm install ejs --save

Create and edit index.js

Create a file called index.js using the contents below.

var app = require('express')();
var session = require('express-session');
const RC = require('@ringcentral/sdk').SDK
var path = require('path')
require('dotenv').config();

var usePKCE = false; // change to true for enabling authorization code with PKCE flow

app.use(session({ secret: 'somesecretstring', tokens: '' }));
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')

REDIRECT_URL = process.env.RC_REDIRECT_URL

var rcsdk = new RC({
    'server':       process.env.RC_SERVER_URL,
    'clientId':     process.env.RC_CLIENT_ID,
    'clientSecret': process.env.RC_CLIENT_SECRET,
    'redirectUri':  REDIRECT_URL
});

var server = require('http').createServer(app);
server.listen(5000);
console.log("listen to port 5000")

app.get('/index', function(req, res) {
  res.redirect("/")
})

app.get('/', async function(req, res) {
  var platform = rcsdk.platform()
  if (req.session.tokens != undefined) {
    platform.auth().setData(req.session.tokens)
    if (await platform.loggedIn()) {
      return res.render('test')
    }
  } else {
    res.render('index', {
      authorize_uri: platform.loginUrl({
        redirectUri: REDIRECT_URL,
        usePKCE,
      })
    });
  }
})

app.get('/logout', async function(req, res) {
  if (req.session.tokens != undefined) {
    var platform = rcsdk.platform()
    platform.auth().setData(req.session.tokens)
    if (platform.loggedIn()) {
      try {
        var resp = await platform.logout()
        console.log("logged out")
      } catch (e) {
        console.log(e)
      }
    }
    req.session.tokens = null
  }
  res.redirect("/")
});

app.get('/oauth2callback', async function(req, res) {
  if (req.query.code) {
    try {
      var platform = rcsdk.platform()
      var resp = await platform.login({
        code: req.query.code,
        redirectUri: REDIRECT_URL
      })
      req.session.tokens = await resp.json()
      console.log(req.session.tokens)
      res.redirect("/test")
    } catch (e) {
      res.send('Login error ' + e);
    }
  } else {
    res.send('No Auth code');
  }
});

app.get('/test', function(req, res) {
  if (req.session.tokens != undefined) {
    var platform = rcsdk.platform()
    platform.auth().setData(req.session.tokens)
    if (platform.loggedIn()) {
      if (req.query.api == "extension") {
        var endpoint = "/restapi/v1.0/account/~/extension"
        var params = {}
        return callGetMethod(platform, endpoint, params, res)
      } else if (req.query.api == "extension-call-log") {
        var endpoint = "/restapi/v1.0/account/~/extension/~/call-log"
        var params = {}
        return callGetMethod(platform, endpoint, params, res)
      } else if (req.query.api == "account-call-log") {
        var endpoint = "/restapi/v1.0/account/~/call-log"
        var params = {}
        return callGetMethod(platform, endpoint, params, res)
      }
    }
  }
  res.redirect("/")
});

async function callGetMethod(platform, endpoint, params, res) {
  try {
    var resp = await platform.get(endpoint, params)
    var jsonObj = await resp.json()
    res.send(JSON.stringify(jsonObj))
  } catch (e) {
    res.send("Error: " + e.message)
  }
}

Create a views folder and create an index.ejs and a test.ejs files under the views folder

Create a file called index.ejs. In this file, we'll implement the login page.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>RingCentral Authorization Code Flow Authentication</title>
  </head>
  <body>
    <h2>
        RingCentral Authorization Code Flow Authentication
    </h2>
    <a href="<%- authorize_uri %>">Login RingCentral Account</a>
  </body>
</html>

Create a file called test.ejs. In this file, we'll add a few API call test cases and a logout button.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
  <b><a href="/logout">Logout</a></b>
  <h2>Call APIs</h2>
  <ul>
      <li><a href="/test?api=extension">Read Extension Info</a></li>
      <li><a href="/test?api=extension-call-log">Read Extension Call Log</a></li>
      <li><a href="/test?api=account-call-log">Read Account Call Log</a></li>
  </ul>
</body>
</html>

Run your code

You are almost done. Now run your script.

$ node index.js

Open a Web browser and load localhost:5000

Install RingCentral Python SDK and Flask framework

$ pip install ringcentral
$ pip install python-dotenv
$ pip install flask

Create an index.py

Create a file called index.py using the contents below.

#!/usr/bin/env python
from ringcentral import SDK
import logging,os,sys,urllib
from flask import Flask, render_template, request, session
from dotenv import load_dotenv
load_dotenv()

REDIRECT_URL = os.environ.get('RC_REDIRECT_URL')

rcsdk = SDK( os.environ.get('RC_CLIENT_ID'),
             os.environ.get('RC_CLIENT_SECRET'),
             os.environ.get('RC_SERVER_URL') )
platform = rcsdk.platform()

app = Flask(__name__)
app.secret_key = 'somesecretstring'

@app.route('/')
@app.route('/index')
def login():
    base_url = SERVER + '/restapi/oauth/authorize'
    params = (
        ('response_type', 'code'),
        ('redirect_uri', REDIRECT_URL),
        ('client_id', os.environ.get('RC_CLIENT_ID')),
        ('state', 'initialState')
    )
    auth_url = base_url + '?' + urllib.parse.urlencode(params)
    return render_template('index.html', authorize_uri=auth_url)

@app.route('/oauth2callback', methods=['GET'])
def oauth2callback():
    platform = rcsdk.platform()
    auth_code = request.values.get('code')
    try:
        platform.login('', '', '', auth_code, REDIRECT_URL)
    except:
        sys.exit("Unable to authenticate to platform. Check credentials.")
    tokens = platform.auth().data()
    session['sessionAccessToken'] = tokens
    return render_template('test.html')

@app.route('/test', methods=['GET'])
def callapi():
    platform = rcsdk.platform()
    platform.auth().set_data(session['sessionAccessToken'])
    if platform.logged_in() == False:
        return login()
    api = request.values.get('api')
    if api == "extension":
        resp = platform.get("/restapi/v1.0/account/~/extension")
        return resp.response()._content
    elif api == "extension-call-log":
        resp = platform.get("/restapi/v1.0/account/~/extension/~/call-log")
        return resp.response()._content
    elif api == "account-call-log":
        resp = platform.get("/restapi/v1.0/account/~/call-log")
        return resp.response()._content
    else:
        return render_template('test.html')

@app.route('/logout', methods=['GET'])
def logout():
    platform = rcsdk.platform()
    platform.auth().set_data(session['sessionAccessToken'])
    if platform.logged_in():
        platform.logout()
    session.pop('sessionAccessToken', None)
    return login()

def main():
    logging.info("Being run from the command line. Exiting safely.")
    sys.exit(0)

if __name__ == "__main__":
    main()

Create a templates folder and create an index.html and a test.html file under the templates folder

Create a file called index.html. In this file, we'll implement the login page.

<!DOCTYPE html>
<html>
  <head>
      <meta charset="UTF-8">
      <title>RingCentral Authorization Code Flow Authentication</title>
  </head>
  <body>
    <h2>
        RingCentral Authorization Code Flow Authentication
    </h2>
    <a href="{{ authorize_uri }}">Login RingCentral Account</a>
  </body>
</html>

Create a file called test.html. In this file, we'll add a few API call test cases and a logout button.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
  <b><a href="/logout">Logout</a></b>
  <h2>Call APIs</h2>
  <ul>
      <li><a href="/test?api=extension">Read Extension Info</a></li>
      <li><a href="/test?api=extension-call-log">Read Extension Call Log</a></li>
      <li><a href="/test?api=account-call-log">Read Account Call Log</a></li>
  </ul>
</body>
</html>

Run your code

You are almost done. Now run your script.

$ FLASK_APP=index.py flask run

Open a Web browser and load localhost:5000

Install RingCentral PHP SDK

$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar require ringcentral/ringcentral-php vlucas/phpdotenv

Create an index.php

Create a file called index.php. In this file we'll implement the login page.

<!DOCTYPE html>
<?php
require(__DIR__ . 'vendor/autoload.php');
use RingCentral\SDK\SDK;
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../');
$dotenv->load();
session_start();

$REDIRECT_URL = $_ENV['RC_REDIRECT_URL'];

$rcsdk = new RingCentral\SDK\SDK( $_ENV['RC_CLIENT_ID'],
                                  $_ENV['RC_CLIENT_SECRET'],
                                  $_ENV['RC_SERVER_URL'] );
$platform = $rcsdk->platform();
$platform->login( $_ENV['RC_USERNAME'],
                  $_ENV['RC_EXTENSION'],
                  $_ENV['RC_PASSWORD'] );

// Using the authUrl to call the platform function
$url = $platform->authUrl(array(
          'redirectUri' => $REDIRECT_URL,
          'state' => 'initialState',
          'brandId' => '',
          'display' => '',
          'prompt' => ''
        ));
?>

<html>
  <head>
      <meta charset="UTF-8">
      <title>RingCentral Authorization Code Flow Authentication</title>
  </head>
  <body>
    <h2>
      RingCentral Authorization Code Flow Authentication
    </h2>
    <a href="<?php echo $url; ?>">Login RingCentral Account</a>
  </body>
</html>

Create a test.html file

Create a file called test.html. In this file we'll add a few API call test cases and a logout button.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
  <b><a href="http://localhost:5000/engine.php?logout">Logout</a></b>
  <h2>Call APIs</h2>
  <ul>
      <li><a href="http://localhost:5000/engine.php?api=extension">Read Extension Info</a></li>
      <li><a href="http://localhost:5000/engine.php?api=extension-call-log">Read Extension Call Log</a></li>
      <li><a href="http://localhost:5000/engine.php?api=account-call-log">Read Account Call Log</a></li>
  </ul>
</body>
</html>

Create an engine.php file

Create a file called engine.php. In this file we'll handle the OAuth2 callback and RingCentral API calls.

<?php
require_once(__DIR__ . '/vendor/autoload.php');
use RingCentral\SDK\Http\HttpException;
use RingCentral\SDK\Http\ApiResponse;
use RingCentral\SDK\SDK;
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../');
$dotenv->load();
session_start();

$REDIRECT_URL = $_ENV['RC_REDIRECT_URL'];
$LOCAL_SERVER = 'http://localhost:5000';


$rcsdk = new RingCentral\SDK\SDK( $_ENV['RC_CLIENT_ID'],
                                  $_ENV['RC_CLIENT_SECRET'],
                                  $_ENV['RC_SERVER_URL'] );
$platform = $rcsdk->platform();

if (isset($_REQUEST['oauth2callback'])){
  if (!isset($_GET['code'])) {
      return;
  }
  $qs = $platform->parseAuthRedirectUrl($_SERVER['QUERY_STRING']);
  $qs["redirectUri"] = $REDIRECT_URL;

  $platform->login($qs);
  $_SESSION['sessionAccessToken'] = $platform->auth()->data();
  header("Location: " + $LOCAL_SERVER + "/test.html");
}

if (!isset($_SESSION['sessionAccessToken'])) {
    header("Location: " + $LOCAL_SERVER);
    exit();
}else{
    $platform->auth()->setData((array)$_SESSION['sessionAccessToken']);
    if (!$platform->loggedIn()) {
        header("Location: " + $LOCAL_SERVER);
        exit();
    }
    if (isset($_REQUEST['logout'])){
        unset($_SESSION['sessionAccessToken']);
        $platform->logout();
        header("Location: " + $LOCAL_SERVER);
        exit();
    }elseif (isset($_REQUEST['api'])){
        if ($_REQUEST['api'] == "extension") {
            $endpoint = "/restapi/v1.0/account/~/extension";
            callGetRequest($endpoint, null);
        }elseif ($_REQUEST['api'] == "extension-call-log") {
            $endpoint = "/restapi/v1.0/account/~/extension/~/call-log";
            $params = array(
                'fromDate' => '2018-12-01T00:00:00.000Z',
              );
            callGetRequest($endpoint, $params);
        }elseif ($_REQUEST['api'] == "account-call-log") {
            $endpoint = "/restapi/v1.0/account/~/call-log";
            $params = array(
                'fromDate' => '2018-12-01T00:00:00.000Z',
              );
            callGetRequest($endpoint, $params);
        }
    }
}

function callGetRequest($endpoint, $params){
  global $platform;
  try {
    $resp = $platform->get($endpoint, $params);
    echo "<p>".$resp->text()."</p>";
  } catch (\RingCentral\SDK\Http\ApiException $e) {
    print 'Expected HTTP Error: ' . $e->getMessage() . PHP_EOL;
  }
}
?>

Run your code

You are almost done. Now run your script.

$ php -S localhost:5000

Open a Web browser and load localhost:5000

Initiate the project

We use .NET core which is cross-platform. You can get it here.

mkdir authorization-demo
cd authorization-demo
dotnet new sln
mkdir my-project
cd my-project
dotnet new web
cd ..
dotnet sln add ./my-project/my-project.csproj
cd my-project
dotnet add package RingCentral.Net
dotnet add package Newtonsoft.Json

Edit Startup.cs

Override Startup.cs with content below. Be sure to edit the variables in with your app credentials.

using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using RingCentral;
using Newtonsoft.Json;

namespace my_project
{
    public class Startup
    {
        static RestClient restClient;
        private const string SESSION_TOKEN_KEY = "rc-token";
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().AddSessionStateTempDataProvider();
            services.AddSession();
        }

        private static string Html(string body)
        {
            return $@"<!doctype html><html><body>{body}</body></html>";
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
            app.UseSession();
            app.Run(async (context) =>
            {
                restClient = new RestClient(
                    Environment.GetEnvironmentVariable("RC_CLIENT_ID"),
                    Environment.GetEnvironmentVariable("RC_CLIENT_SECRET"),
                    Environment.GetEnvironmentVariable("RC_SERVER_URL"));
                var tokenString = context.Session.GetString(SESSION_TOKEN_KEY);
                if (tokenString != null)
                {
                    restClient.token = JsonConvert.DeserializeObject<TokenInfo>(tokenString);
                }
                else if (context.Request.Path != "/oauth2callback")
                {
                    var oauthUri = restClient.AuthorizeUri(Environment.GetEnvironmentVariable("RC_REDIRECT_URL"));
                    await context.Response.WriteAsync(
                        Html($"<h2>RingCentral Authorization Code Flow Authentication</h2><a href=\"{oauthUri}\">Login RingCentral Account</a>"));
                    return;
                }

                switch (context.Request.Path)
                {
                    case "/":
                        await context.Response.WriteAsync(Html(@"<b><a href=\"/logout\">Logout</a></b>
                            <h2>Call APIs</h2>
                            <ul>
                                <li><a href=\"/test?api=extension\" target=\"_blank\">Read Extension Info</a></li>
                                <li><a href=\"/test?api=extension-call-log\" target=\"_blank\">Read Extension Call Log</a></li>
                                <li><a href=\"/test?api=account-call-log\" target=\"_blank\">Read Account Call Log</a></li>
                            </ul>"));
                        break;
                    case "/oauth2callback":
                        context.Request.Query.TryGetValue("code", out var codes);
                        var code = codes.First();
                        await restClient.Authorize(code, Environment.GetEnvironmentVariable("RC_REDIRECT_URL"));
                        context.Session.SetString(SESSION_TOKEN_KEY, JsonConvert.SerializeObject(restClient.token));
                        context.Response.Redirect("/");
                        break;
                    case "/test":
                        context.Request.Query.TryGetValue("api", out var apis);
                        var api = apis.First();
                        var result = "";
                        switch (api)
                        {
                            case "extension":
                                result = await restClient.Get<string>("/restapi/v1.0/account/~/extension");
                                break;
                            case "extension-call-log":
                                result = await restClient.Get<string>("/restapi/v1.0/account/~/extension/~/call-log");
                                break;
                            case "account-call-log":
                                result = await restClient.Get<string>("/restapi/v1.0/account/~/call-log");
                                break;
                        }

                        await context.Response.WriteAsync(Html($"<pre>{result}</pre>"));
                        break;
                    case "/logout":
                        await restClient.Revoke();
                        context.Session.Remove(SESSION_TOKEN_KEY);
                        context.Response.Redirect("/");
                        break;
                    default:
                        context.Response.StatusCode = 404;
                        break;
                }
            });
        }
    }
}

Run your code

You are almost done. Now run your app.

$ dotnet run

Open a Web browser and load localhost:5000

If you meet "Unable to configure HTTPS endpoint" issue, please read this article.

Create a Java project (using Eclipse IDE)

  • Create a new Java project
  • Select the Gradle Project wizard
  • Enter project name "Authentication"
  • Open the build.gradle file and add the RingCentral Java SDK, Javax Servlet, and Jetty to the project as shown below:
dependencies {
    // ...
    compile 'com.ringcentral:ringcentral:1.0.0-beta13'
    compile 'javax.servlet:javax.servlet-api:4.0.1'
    compile 'org.eclipse.jetty:jetty-server:9.4.19.v20190610'
}
  • Right-click the project in the Package Explorer and choose "Refresh Gradle Project" under the "Gradle" sub-menu

Create a new Java Class

Select "File -> New -> Class" to create a new Java class named "Authorization_Flow"

public class AuthorizationFlow {

  public static void main(String[] args) {
    // TODO Auto-generated method stub

  }
}

Edit the file "Authorization_Flow.java"

Be sure to edit the variables in ALL CAPS with your app and user credentials.

package com.ringcentral;

import com.ringcentral.RestClient;
import com.ringcentral.RestException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ringcentral.definitions.TokenInfo;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;

public class AuthorizationFlow extends AbstractHandler {
    static RestClient rc;
    private static String TOKEN_KEY = "rc-token";
    private static String REDIRECT_URI = "http://localhost:5000/oauth2callback";

    public static void main(String[] args) throws Exception {
    rc = new RestClient( System.getenv("RC_CLIENT_ID"),
                 System.getenv("RC_CLIENT_SECRET"),
                 System.getenv("RC_SERVER_URL") );
    try {
        rc.authorize( System.getenv("RC_USERNAME"),
              System.getenv("RC_EXTENSION"),
              System.getenv("RC_PASSWORD") );
    } catch (RestException | IOException e) {
        e.printStackTrace();
    }

        Server server = new Server(5000);
        server.setHandler(new AuthorizationFlow());
        server.start();
        server.join();
    }

    @Override
    public void handle(String target, Request baseRequest,
               HttpServletRequest request, HttpServletResponse response)
    throws IOException {
        response.setContentType("text/html; charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);
        baseRequest.setHandled(true);
        Cookie[] cookiesArray = request.getCookies();
        List<Cookie> cookies = Arrays.asList(cookiesArray);
        List<Cookie> filteredCookies = cookies.stream().filter(c -> c.getName().equals(TOKEN_KEY)).collect(Collectors.toList());
        String requestUri = request.getRequestURI();
        if (filteredCookies.size() > 0) {
            String base64String = filteredCookies.get(0).getValue();
            byte[] decodedBytes = Base64.getDecoder().decode(base64String);
            String tokenString = new String(decodedBytes);
            rc.token = JSON.parseObject(tokenString, TokenInfo.class);
        } else if (!requestUri.equals("/oauth2callback")) {
            response.getWriter().println("<h2>RingCentral Authorization Code Flow Authentication</h2>"
                     + "<a href=\"" + rc.authorizeUri(REDIRECT_URI)
                     + "\">Login RingCentral Account</a>");
            return;
        }
        System.out.println(requestUri);
        switch (requestUri) {
        case "/":
            response.getWriter().println("<b><a href=\"/logout\">Logout</a></b>\n" +
                                         "<h2>Call APIs</h2>\n" +
                                         "<ul>\n" +
                                         "<li><a href=\"/test?api=extension\">Read Extension Info</a></li>\n" +
                                         "<li><a href=\"/test?api=extension-call-log\">Read Extension Call Log</a></li>\n" +
                                         "<li><a href=\"/test?api=account-call-log\">Read Account Call Log</a></li>\n" +
                                         "</ul>");
            break;
        case "/oauth2callback":
            String code = request.getParameter("code");
            try {
                rc.authorize(code, REDIRECT_URI);
            } catch (RestException e) {
                e.printStackTrace();
            }
            String base64String = Base64.getEncoder().encodeToString(JSON.toJSONString(rc.token).getBytes());
            Cookie cookie2 = new Cookie(TOKEN_KEY, base64String);
            cookie2.setMaxAge(999999999);
            response.addCookie(cookie2);
            response.sendRedirect("/");
            break;
        case "/test":
            String api = request.getParameter("api");
            String result = "";
            switch (api) {
            case "extension":
                    try {
                        result = JSON.toJSONString(rc.restapi().account().extension().list(), SerializerFeature.PrettyFormat);
                    } catch (RestException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                break;
            case "extension-call-log":
                    try {
                        result = JSON.toJSONString(rc.restapi().account().extension().callLog().list(), SerializerFeature.PrettyFormat);
                    } catch (RestException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                break;
            case "account-call-log":
                    try {
                        result = JSON.toJSONString(rc.restapi().account().callLog().list(), SerializerFeature.PrettyFormat);
                    } catch (RestException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                break;
            }

            response.getWriter().println("<pre>" + result + "</pre>");
            break;
        case "/logout":
            try {
                rc.revoke();
            } catch (RestException e) {
                e.printStackTrace();
            }
            Cookie cookie = new Cookie(TOKEN_KEY, "");
            cookie.setMaxAge(0);
            response.addCookie(cookie);
            response.sendRedirect("/");
            break;
        default:
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            break;
        }
    }
}

Run your code

You are almost done. Now run your app from Eclipse. Then Open a Web browser and enter localhost:5000.

Create a new Rails app and install the RingCentral Ruby SDK

$ rails new authorization-flow
$ cd authorization-flow
$ bundle add ringcentral-sdk
$ bundle add dotenv

Create a new controller

$ rails generate controller main login

Browse to the "app/controllers" folder and edit the main_controller.rb. Be sure to edit the variables in <ALL CAPS> with your app credentials.

class MainController < ActionController::Base
  require 'ringcentral'
  require 'dotenv/load'

  REDIRECT_URL = ENV['RC_REDIRECT_URL']

  $rc = RingCentral.new( ENV['RC_CLIENT_ID'],
                         ENV['RC_CLIENRT_SECRET'],
                         ENV['RC_SERVER_URL'] )

  def login
    base_url = $rc.authorize_uri(REDIRECT_URL, "initialState")
    @authorize_uri = base_url
  end

  def oauth2callback
    auth_code = params[:code]
    $rc.authorize(username: nil, extension: nil, password: nil,
                  auth_code: auth_code, redirect_uri: REDIRECT_URL)
    # Save tokens to session
    session[:tokens] = $rc.token
    redirect_to "/main/test"
  end

  def callapis
    req = params[:api]
    api = req.split(/=/)
    if $rc.token == nil
      return redirect_to "/main/login"
    end

    if api[1] == 'extension'
      resp = $rc.get("/restapi/v1.0/account/~/extension")
    elsif api[1] == "extension-call-log"
      resp = $rc.get("/restapi/v1.0/account/~/extension/~/call-log")
    elsif api[1] == "account-call-log"
      resp = $rc.get("/restapi/v1.0/account/~/call-log")
    elsif api[0] == "logout"
      $rc.revoke()
      session[:tokens] = nil
      return redirect_to "/main/login"
    else
      return redirect_to "/main/test"
    end
    render({plain: resp.body})
  end
end

Edit the routes.rb file

Browse the the "config" folder and edit the file routes.rb

Rails.application.routes.draw do
  get 'main/login'
  get 'main/test'
  match '/main/:api' => 'main#callapis', via: :get
  match '/oauth2callback' => 'main#oauth2callback', via: :get
end

Browse to the "app/views/main" folder and edit the login.html.erb.

<!DOCTYPE html>
<html>
  <head>
      <meta charset="UTF-8">
      <title>RingCentral Authorization Code Flow Authentication</title>
  </head>
  <body>
    <h2>
        RingCentral Authorization Code Flow Authentication
    </h2>
    <a href="<%= @authorize_uri %>">Login RingCentral Account</a>
  </body>
</html>

Implement a test page

$ rails generate controller main test

Do not overwrite the main_controller.rb

Answer "no" to the overwrite main_controller.rb confirmation!

Browse to the "app/views/main" folder and edit the test.html.erb.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
  <b><a href="logout">Logout</a></b>
  <h2>Call APIs</h2>
  <ul>
      <li><a href="api=extension">Read Extension Info</a></li>
      <li><a href="api=extension-call-log">Read Extension Call Log</a></li>
      <li><a href="api=account-call-log">Read Account Call Log</a></li>
  </ul>
</body>
</html>

Run your code

You are almost done. Now run your script.

$ bin/rails server -p 5000

Open a Web browser and load localhost:5000/main/login

Need Help?

Having difficulty? Feeling frustrated? Receiving an error you don't understand? Our community is here to help and may already have found an answer. Search our community forums, and if you don't find an answer please ask!

Search the forums »

Graduate Your App

Congratulations on creating your first RingCentral application. The last step is to graduate your application. We recommend going through this process for your first application so you can understand the steps to take in the future, but also to come to appreciate the care taken by RingCentral to ensure that only high-quality apps are allowed into our production environment.