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