Authentication

You need to:

  1. Create an OAuth 2.0 client
  2. Get a client access token

Token Endpoint

URI Credentials
https://id.wgtwo.com/oauth2/token basic auth

We only support the client credential flow for obtaining an access token. That is, the access token will authenticate the product itself and not a specific user.

Reach out if your application only supports passing client ID and client in the request body.

As given by RFC 6749, it is recommended to use the HTTP Basic authentication scheme for client ID and client secret. By default, that is the only method we support for authenticating the client.

Create OAuth 2.0 Client

In order to authenticate our APIs, you will need to create an OAuth 2.0 client. This client is tied to a product in Developer Portal.

Create Client

  1. Sign up at developer.mobility.cisco.com. Use your work email.
  2. Create an organization
  3. Create a product
  4. Go to the "Technical integration" tab, and click "ADD OAUTH CLIENT":
Field Value
Client description This description is for your own benefit, choose whatever you want

The generated credentials will be displayed only once, so make sure to save them.

You Can Now Authenticate Towards Our APIs

You can now start playing with our APIs.

In order to get your product displayed in our storefront, you will need to fill in additional details, but these details are not required for the technical integration (using APIs).

Get Client Access Token

Prerequisites

Use a Library

We do not recommend implementing this flow manually. There are good OAuth 2.0 libraries for all common languages.

You are expected to reuse the obtained token until it expires. It can be kept in memory, and you are not required to keep a shared cache between your servers.

Supplying an up-to-date token with automatic refreshing is handled automatically for some libraries. See:

Example Code Dependency

<dependency>
    <groupId>com.wgtwo.api</groupId>
    <artifactId>auth</artifactId>
    <version>0.0.5</version>
</dependency>

Example Get Access Token

Get client credentials for sms.text:send_from_subscriber and sms.text:send_to_subscriber.


#!/usr/bin/env bash
curl \
  --user "$CLIENT_ID":"$CLIENT_SECRET" \
  --data grant_type="client_credentials" \
  --data scope="sms.text:send_from_subscriber sms.text:send_to_subscriber" \
  https://id.wgtwo.com/oauth2/token

package com.example.oauth2

import com.wgtwo.auth.WgtwoAuth
import io.grpc.CallCredentials

fun main() {
    val clientId = System.getenv("CLIENT_ID")
    val clientSecret = System.getenv("CLIENT_SECRET")
    val wgtwoAuth = WgtwoAuth.builder(clientId, clientSecret).build()

    val scope = "subscription.read subscription.write"

    // Recommended: Get token source (cache with automatic refresh)
    val tokenSource = wgtwoAuth.clientCredentials.newTokenSource(scope)
    println("Got access token ${tokenSource.fetchToken().accessToken}")

    // This token source can be used to create call credentials for use with gRPC
    val callCredentials: CallCredentials = tokenSource.callCredentials()

    // Alternative: Explicit fetch of single token
    val token = wgtwoAuth.clientCredentials.fetchToken(scope)
    println("Got access token ${token.accessToken} which expires at ${token.expiry}")
}

package main

import (
    "context"
    "fmt"
    "golang.org/x/oauth2/clientcredentials"
    "os"
)

func main() {
    scopes := []string{"sms.text:send_from_subscriber", "sms.text:send_to_subscriber"}
    clientCredentialsConfig := &clientcredentials.Config{
        ClientID:     os.Getenv("CLIENT_ID"),
        ClientSecret: os.Getenv("CLIENT_SECRET"),
        Scopes:       scopes,
        TokenURL:     "https://id.wgtwo.com/oauth2/token",
    }
    tokenSource := clientCredentialsConfig.TokenSource(context.Background())

    token, err := tokenSource.Token()
    if err != nil {
        panic(err)
    }

    fmt.Printf("Got access token %v which expires at %v
", token.AccessToken, token.Expiry)
}

Example Use Access Token


#!/usr/bin/env bash
grpcurl \
  -d '
  {
    "content": "My text message",
    "fromSubscriber": "+47xxxxxxxx",
    "toAddress": "+47yyyyyyyy"
  }
  ' \
  sandbox.api.shamrock.wgtwo.com:443 \
  wgtwo.sms.v1.SmsService/SendTextFromSubscriber

package com.example.oauth2

import com.wgtwo.api.v1.sms.SmsProto
import com.wgtwo.api.v1.sms.SmsServiceGrpc
import com.wgtwo.auth.WgtwoAuth
import io.grpc.ManagedChannelBuilder

fun main() {
    val clientId = System.getenv("CLIENT_ID")
    val clientSecret = System.getenv("CLIENT_SECRET")
    val wgtwoAuth = WgtwoAuth.builder(clientId, clientSecret).build()

    // Get token source (cache with automatic refresh)
    val tokenSource = wgtwoAuth.clientCredentials.newTokenSource("sms.text:send_from_subscriber")

    val channel = ManagedChannelBuilder.forTarget("sandbox.api.shamrock.wgtwo.com:443").build()
    val stub = SmsServiceGrpc.newBlockingStub(channel)
        .withCallCredentials(tokenSource.callCredentials())

    val request = SmsProto.SendTextFromSubscriberRequest.newBuilder().apply {
        fromSubscriber = "+4799000000"
        toAddress = "+4799990000"
        content = "Testing 1, 2, 3"
    }.build()
    val response = stub.sendTextFromSubscriber(request)
    println("response:
$response")
}

package main

import (
    "context"
    "fmt"
    wgtwoSipBreakout "github.com/working-group-two/wgtwoapis/wgtwo/sipbreakout/v1"
    "golang.org/x/oauth2"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
    "google.golang.org/grpc/credentials/oauth"
)

// Token source from above example
var tokenSource oauth2.TokenSource

func main() {
    conn, err := grpc.Dial(
        "sandbox.api.shamrock.wgtwo.com:443",
        grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")),
        grpc.WithPerRPCCredentials(oauth.TokenSource{TokenSource: tokenSource}),
    )

    if err != nil {
        panic(err)
    }
    defer conn.Close()

    client := wgtwoSipBreakout.NewSipBreakoutServiceClient(conn)
    request := &wgtwoSipBreakout.UpsertRegistrationRequest{
        Registration: &wgtwoSipBreakout.Registration{
            MobileOriginatingPrefix: "11",
            MobileTerminatingPrefix: "22",
            SipUri:                  "sips:example.com:8888",
            RouteType:               wgtwoSipBreakout.RouteType_ROUTE_TYPE_LOOP,
        },
    }
    response, err := client.UpsertRegistration(context.Background(), request)

    if err != nil {
        panic(err)
    }

    fmt.Printf("Got status: %v", response.StatusCode)
}

Resources

JSON Web Key Set

JWKS endpoint: https://id.wgtwo.com/.well-known/jwks.json

All issued JWTs are signed using the RS256 signing algorithm.

The JWT is signed using one of these keys, but the endpoint may contain multiple keys to allow key rotation.

It is recommended to use a library that fetches the keys dynamically as they may be rotated without notice.