In order to be able to access ONE Reporting service, a client should add Authorization: Bearer TOKEN header to each request. The client should be provisioned with both client_id and client_secret for QA/DEV and PROD environments. After these values are obtained, client_id should be registered within ONE Reporting system.

Note: token url for stage (UAT) https://id-uat.b2b.yahooinc.com/identity/oauth2/access_token

Note: token url for PROD https://id.b2b.yahooinc.com/identity/oauth2/access_token

Note: client_secret is always private and should never be shared.

    Below is the code sample for OAuth 2.0 access token generation for ONE Reporting.

    
package oauth2;

import java.util

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import org.jose4j.jws.{AlgorithmIdentifiers, JsonWebSignature}
import org.jose4j.jwt.{JwtClaims, NumericDate}
import org.jose4j.keys.HmacKey
import org.springframework.http.converter.FormHttpMessageConverter
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.http.{HttpEntity, HttpHeaders, HttpMethod, MediaType}
import org.springframework.util.{LinkedMultiValueMap, MultiValueMap}
import org.springframework.web.client.RestTemplate

import scala.collection.JavaConverters._

/**
 * Is used to retrieve OAuth 2.0 access token in Identity B2B platform
 */
object AccessTokenFetchService {

  /** Fetch the token by the provided credentials
    * @param credentials see: [[Credentials]]
    * @return OAuth 2.0 access token along, see: [[AccessToken]]
    */
  def fetch(credentials: Credentials): AccessToken = {
    val payload = constructPayload(credentials)
    val httpEntity = new HttpEntity[MultiValueMap[String, String]](payload, prepareHttpHeaders)
    // token request is a POST HTTP request on the Identity B2B platform endpoint url
    // with the payload consisting of url-encoded query params
    restTemplate.exchange(credentials.tokenUrl, HttpMethod.POST, httpEntity, classOf[AccessToken]).getBody
  }

  // payload key-value pairs
  private def constructPayload(credentials: Credentials): MultiValueMap[String, String] = {
    val map = Map(
      "client_assertion_type" -> credentials.clientAssertionType,
      "grant_type" -> credentials.grantType,
      "scope" -> credentials.scope,
      "realm" -> credentials.realm,
      "client_assertion" -> generateJsonWebToken(credentials)
    ).map { case (name, value) => name -> Seq(value).asJava }.asJava
    new LinkedMultiValueMap[String, String](map)
  }

  // JWT token generation by the provided credentials
  private def generateJsonWebToken(credentials: Credentials): String = {
    val claims = new JwtClaims
    claims.setIssuedAt(NumericDate.now)
    claims.setExpirationTimeMinutesInTheFuture(5)
    claims.setSubject(credentials.clientId)
    claims.setIssuer(credentials.clientId)
    claims.setAudience(getAudience(credentials.tokenUrl, credentials.realm))
    claims.setGeneratedJwtId()
    val key = new HmacKey(credentials.clientSecret.getBytes("UTF-8"))
    val jws = new JsonWebSignature
    jws.setPayload(claims.toJson)
    jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256)
    jws.setKey(key)
    jws.setDoKeyValidation(false)
    jws.getCompactSerialization
  }

  private def getAudience(url: String, realm: String) = String.format("%s?realm=%s", url, realm)

  // HTTP headers expected by Identity B2B platform
  private def prepareHttpHeaders = {
    val headers = new HttpHeaders
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED)
    headers.setAccept(Seq(MediaType.APPLICATION_JSON).asJava)
    headers
  }

  // spring-web rest template to make http calls
  private lazy val restTemplate = {
    val restTemplate = new RestTemplate
    val mapper = new ObjectMapper
    mapper.registerModule(DefaultScalaModule)
    val jacksonConverter = new MappingJackson2HttpMessageConverter(mapper)
    restTemplate.setMessageConverters(util.Arrays.asList(jacksonConverter, new FormHttpMessageConverter))
    restTemplate
  }
}
    
  
    
package oauth2;

/**
  * The credentials needed for OAuth 2.0 token
  * generation in Identity B2B platform
  */
trait Credentials {
  def tokenUrl: String
  def scope: String
  def clientId: String
  def clientSecret: String
  def realm: String
  def grantType: String
  def clientAssertionType: String
}
    
  
    
package oauth2;

/**
  * Container for the credentials to generate One Reporting OAuth 2.0 token
  * @param tokenUrl identity B2B platform token generation endpoint url
  * @param clientId the provided by One Central client id
  * @param clientSecret the provided by One Central client secret
  * @param scope OAuth 2.0 scope, defaults to "one"
  * @param realm OAuth 2.0 realm, defaults to "aolcorporate/aolexternals"
  * @param grantType OAuth 2.0 grant type, defaults to "client_credentials"
  * @param clientAssertionType OAuth 2.0 assertion type with the default value
  */
case class ReportingCredentials(tokenUrl: String,
                                clientId: String,
                                clientSecret: String,
                                scope: String = "one",
                                realm: String = "aolcorporate/aolexternals",
                                grantType: String = "client_credentials",
                                clientAssertionType: String = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
  extends Credentials
    
  
    
package oauth2;

import com.fasterxml.jackson.annotation.JsonProperty

/**
  * Identity B2B platform successful response on token generation
  * @param token the generated access token
  * @param scope OAuth 2.0 scope of the generated access token
  * @param tokenType OAuth 2.0 token type (Bearer)
  * @param expiresIn expiration time in seconds
  */
case class AccessToken(@JsonProperty("access_token") token: String,
                       @JsonProperty("scope") scope: String,
                       @JsonProperty("token_type") tokenType: String,
                       @JsonProperty("expires_in") expiresIn: Int)
    
  

For DSP Users:

    In order to be able to access ONE Reporting service, a client should add Authorization: Bearer TOKEN header and Authorizer: dsp (not case-sensitive) header to each request. Once the user is created or has access to DSP UI, then get both client_id and client_secret for QA/DEV and PROD environments.
The process to get client_id and client_secret is described in this link. The next step is to generate an access token using the client ID and client secret.
The process to generate access token is described in Generate the Access Token

For Backstage Users:

    In order to be able to access ONE Reporting service, a client should add Authorization: Bearer TOKEN header and Authorizer: dsp (not case-sensitive) header to each request. The client should be provisioned with both client_id and client_secret for QA/DEV and PROD environments. To obtain these values, please contact pmp@yahooinc.com. Once the values are obtained, the next step is to generate an access token using the client ID and client secret.
The process to generate access token is described in Generate the Access Token