Getting started using OAuth's auth code flow

Last updated: 2024-03-25Contributors
Edit this page

Before you get started, make sure you are using the best authentication method for your application. OAuth's auth code flow is ideally suited for applications that need to collect RingCentral credentials for each user of that app. If you are just getting started on the platform, writing a script to be run via the command-line, or facilitating the connection between a server and RingCentral, we recommend you use our JWT flow.

Create an app and obtain credentials

The first thing we need to do is create an app in the RingCentral Developer Console. 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.

Setting the redirect URI for your app

If you are setting up your application manually, be sure to set your redirect URL to the following:

http://localhost:5000/oauth2callback

Redirect URI

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.

<?php
$USE_PKCE = True;

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();

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

// process an oauth redirect
if (isset($_GET['code'])) {
  $qs = $platform->parseAuthRedirectUrl( $_SERVER['QUERY_STRING'] );
  $qs["redirectUri"] = $_ENV['RC_REDIRECT_URL'];
  if ($USE_PKCE) {
    $qs["codeVerifier"] = $_SESSION['sessionCodeVerifier'];
  }
  $platform->login($qs);
  $_SESSION['sessionAccessToken'] = $platform->auth()->data();
}

// seed the SDK with auth context if present
if (isset($_SESSION['sessionAccessToken'])) {
  $platform->auth()->setData((array)$_SESSION['sessionAccessToken']);
}

// helper function for calling API and printing results
function callGetRequest($endpoint, $params){
  global $platform;
  try {
    $resp = $platform->get($endpoint, $params);
    header("Content-type: text/plain");
    echo $resp->text();
  } catch (\RingCentral\SDK\Http\ApiException $e) {
    print 'Expected HTTP Error: ' . $e->getMessage() . PHP_EOL;
  }
}

// process a logout request
if (isset( $_REQUEST['logout'] )){
  unset($_SESSION['sessionAccessToken']);
  $platform->logout();

// process a request to call the API as a demo
} elseif ( isset($_REQUEST['api'] )){
  switch ( $_REQUEST['api'] ) {
    case "extension":
      $endpoint = "/restapi/v1.0/account/~/extension";
      callGetRequest($endpoint, null);
      break;
    case "extension-call-log":
      $endpoint = "/restapi/v1.0/account/~/extension/~/call-log";
      $params = array( 'fromDate' => '2018-12-01T00:00:00.000Z' );
      callGetRequest($endpoint, $params);
      break;
    case "account-call-log":
      $endpoint = "/restapi/v1.0/account/~/call-log";
      $params = array( 'fromDate' => '2018-12-01T00:00:00.000Z' );
      callGetRequest($endpoint, $params);
      break;
  }
  // no more output
  exit();
}

if ( $platform->loggedIn() ) {
?>
<html>
<head>
    <meta charset="UTF-8">
      <title>RingCentral OAuth Example (logged in)</title>
</head>
<body>
  <h2>Test out these API functions:</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>
      <li><a href="?logout">Logout</a></li>
  </ul>
</body>
</html>
<?php
} else {
  function base64url_encode($plainText) {          
    $base64 = base64_encode($plainText);
    $base64 = trim($base64, "=");
    $base64url = strtr($base64, '+/', '-_');
    return ($base64url);
  }
  $options = array(
               'redirectUri' => $_ENV['RC_REDIRECT_URL'],
               'state' => 'initialState'
             );
  if ($USE_PKCE) {
    $random = bin2hex(openssl_random_pseudo_bytes(32));
    $verifier = base64url_encode(pack('H*', $random));
    $options['code_challenge'] = base64url_encode( pack('H*', hash('sha256', $verifier)) );
    $options['code_challenge_method'] = 'S256';
    // store the verifier in the session, it will be used when processing the redirect
    $_SESSION['sessionCodeVerifier'] = $verifier;
  }  
  $url = $platform->authUrl( $options );
?>
<html>
  <head>
      <meta charset="UTF-8">
      <title>RingCentral OAuth Example (logged out)</title>
  </head>
  <body>
    <h2>RingCentral OAuth auth code flow demonstration</h2>
    <p><a href="<?php echo $url; ?>">Log into your RingCentral account</a></p>
  </body>
</html>
<?php
} 
?>

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 Java Servlet)

  • Create a new Java project
  • Select the Gradle Project wizard
  • Enter project name "oauth-demo"
  • Open the build.gradle file and add the RingCentral Java SDK and other libraries under dependencies as shown below
apply plugin: 'application'

dependencies {
    // ...
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
    implementation group: 'com.ringcentral', name: 'ringcentral', version: '2.8.2'
    implementation group: 'com.alibaba', name: 'fastjson', version: '1.2.79'
    implementation group: 'org.eclipse.jetty', name: 'jetty-server', version: '11.0.8'
    compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'
}
  • 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 "AuthorizationFlow"

public class AuthorizationFlow {

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

  }
}

Edit the file "AuthorizationFlow.java"

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

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 jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;

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";
  // Make sure this is the same URL as the one i
  private static String REDIRECT_URI = System.getenv("RC_REDIRECT_URL"); 

  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 {
      Server server = new Server(5000);
      server.setHandler(new AuthorizationFlow());
      server.start();
      server.join();
    }
    catch (RestException | IOException e) {
      e.printStackTrace();
    }
  }

  @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)
        + "\"><bold>Login using RingCentral Account</bold></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 using gradle gradle run command. Open a Web browser and enter localhost:5000, you should see 'Login with RingCentral' link, click on that and follow the login process using your sandbox credentials to access the secure page where you can call RingCentral APIs.

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.

#!usr/bin/ruby

# You get the environment parameters from your 
# application dashbord in your developer account 
# https://developers.ringcentral.com

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 »