How to get metadata of Dam Asset while accessing an asset through Asset API from 3rd party app | Community
Skip to main content
Level 2
April 16, 2021
Solved

How to get metadata of Dam Asset while accessing an asset through Asset API from 3rd party app

  • April 16, 2021
  • 3 replies
  • 3552 views

I am using the JWT Bearer Token Server to Server Integration.

and trying to access the asset in AEM through the asset api endpoint from 3rd party application:

I am facing few issues:

1. Everytime a new access token is generated using the JWT Bearer and a call is made to access asset, a new oauth user is generated. Is there a way to restrict this and only use one oauth user over multiple tokens.

2. The oauth user generated has only read permissions on content/dam assets, because of which im not getting the asset metadata in the response as it requires either write/modify/all privileges. Is there a way where we can add these generated oauth user to some group.

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by kpsolanki_1204

Resolved!

The "oauthservice" user defines the privileges on the newly created oauth users when a request with access token comes in.

Added the required privileges to oauthservice system user on the desired path to help it assign the required ACL's to newly generated oauth users.

3 replies

kpsolanki_1204AuthorAccepted solution
Level 2
April 19, 2021

Resolved!

The "oauthservice" user defines the privileges on the newly created oauth users when a request with access token comes in.

Added the required privileges to oauthservice system user on the desired path to help it assign the required ACL's to newly generated oauth users.

kautuk_sahni
Community Manager
Community Manager
April 19, 2021
@kpsolanki_1204, thank you for sharing the solution with community. This would help in posterity. looking forward for more contribution from SME like you.
Kautuk Sahni
Stuart-Downing
June 14, 2021

1. I have no insight into the user generation process you describe. Presumably this user "lives" as long as the lifespan of the access token returned by the JWT exchange process. After the exchange process, I searched the user/group lists for plausible candidates ("oauth", "api", "cloud", "integration") with no luck.

2. I am presuming that adding jcr:all to a path will cause that permission to be inherited by all folders/assets below that path. If I'm mistaken about this then applying to /content/dam might be insufficient

 

Level 2
June 16, 2021

@stuart-downing

The user should get created under /home/users/oauth everytime a access token is generated. By default the access token is valid for an hour and post expiry the respective oauthuser gets purged.

 

"jcr:all" permissions on the dam path should take care of the permissions issue, but not sure why its not working for you.

 

Also please check the Adobe Granite OAuth Server Authentication Handler configuration in felix console is properly configured. 

Double check if this configuration is active via System Console →Main →JASS Console

 

 

Stuart-Downing
June 14, 2021

The code (PHP) follows. As to the question about seeing a new oauth user, I don't see any new users created after the JWT exchange.  Also, the JWT exchange is successful and generate an access token that results in a successful asset api request that is identical to my request made with a local development token, except that the metadata property is empty.

 

<?php
declare(strict_types=1);

namespace LAZ\objects\shared\AdobeExperienceManager\services;


use Doctrine\Common\Cache\Cache;
use Exception;
use Firebase\JWT\JWT;
use GuzzleHttp\Client;
use LAZ\objects\library\HttpStatus;
use LAZ\objects\library\Router\Exception\ForbiddenException;
use LAZ\objects\shared\AdobeExperienceManager\AccessTokenProvider;
use LAZ\objects\shared\AdobeExperienceManager\LazAemInstance;
use stdClass;

class AemServiceCredentialAuthService implements AccessTokenProvider
{
const EXPIRATION_SECONDS_INTERVAL = 60 * 60;
private Cache $cache;
private LazAemInstance $aemInstance;

public function __construct(Cache $cache, LazAemInstance $aemInstance)
{
$this->cache = $cache;
$this->aemInstance = $aemInstance;
}

public function getServiceCredentials(): ?stdClass {
$aemEnv = $_ENV['AEM_AUTHORING_ENV'];
$aemVaultDir = $_ENV['AEM_VAULT_DIR'];
$serviceTokenFile = "$aemVaultDir/service_token_$aemEnv.json";
$credentialsStr = file_get_contents($serviceTokenFile);
if ($credentialsStr === false) {
throw new Exception("Unable to read AEM service credentials from $serviceTokenFile");
}
return json_decode($credentialsStr);
}

public function exchangeJwt(stdClass $options😞 stdClass {
$imsEndpoint = $options->imsEndpoint;
$clientId = $options->clientId;
$jwtPayload = [
'iss' => $options->issuer,
'sub' => $options->subject,
'exp' => $options->expirationTimeSeconds,
'aud' => "https://$imsEndpoint/c/$clientId",
];
foreach ($options->metascopes as $metascope) {
$metascopeKey = "https://$imsEndpoint/s/$metascope";
$jwtPayload[$metascopeKey] = true;
}
$jwtToken = JWT::encode($jwtPayload, $options->privateKey, 'RS256');
$client = new Client();
$uri = "https://$imsEndpoint/ims/exchange/jwt";
$response = $client->post($uri, [
'form_params' => [
'client_id' => $options->clientId,
'client_secret' => $options->clientSecret,
'jwt_token' => $jwtToken,
],
// 'debug' => fopen($_ENV['LOG_PATH'] . '/GuzzleHttp.log', 'a+'),
]);
$statusCode = $response->getStatusCode();
if ($response->getStatusCode() !== HttpStatus::OK) {
if (in_array($response->getStatusCode(), [HttpStatus::UNAUTHORIZED, HttpStatus::FORBIDDEN])) {
throw new ForbiddenException();
}
throw new Exception("Bad status: $statusCode @ $uri\n");
}
return json_decode($response->getBody()->getContents());
}

public function getAccessToken(): string {
$cacheKey = 'AemServiceCredential.AccessToken.' . $this->aemInstance->getAuthoringHost();
$accessToken = $this->cache->fetch($cacheKey);
if ($accessToken === FALSE) {
$accessToken = $this->getAccessTokenFromServiceCredentials();
$this->cache->save($cacheKey, $accessToken);
}
return $accessToken->access_token;
}

public function getAccessTokenFromServiceCredentials(): stdClass {
$serviceCredentials = $this->getServiceCredentials();
return $this->exchangeJwt((object)[
'imsEndpoint' => $serviceCredentials->integration->imsEndpoint,
'issuer' => $serviceCredentials->integration->org,
'subject' => $serviceCredentials->integration->id,
'expirationTimeSeconds' => time() + self::EXPIRATION_SECONDS_INTERVAL,
'metascopes' => explode(',', $serviceCredentials->integration->metascopes),
'clientId' => $serviceCredentials->integration->technicalAccount->clientId,
'clientSecret' => $serviceCredentials->integration->technicalAccount->clientSecret,
'privateKey' => $serviceCredentials->integration->privateKey,
]);
}
}
kautuk_sahni
Community Manager
Community Manager
June 16, 2021
@stuart-downing, Great start in the AEM Community. AEM community need SME's like you. Keep the great work going.
Kautuk Sahni