Skip to content

Commit 7a9e3ec

Browse files
authored
feat: support include ims credentials annotation (#5)
* feat: support ims compatible api params * fix: cache key, imsEnv input and validation as first step * fix: scopes must be an array * chore: tests * feat: read from include-ims-credentials * detect stage namespace and default to stage ims env * fix: stage ims (+ chore: test re-org) * fixes and cleanups * readme update * fix AI generated garbage test file * another round of fixing AI generated tests * readme precisions
1 parent 489d91a commit 7a9e3ec

7 files changed

Lines changed: 188 additions & 131 deletions

File tree

README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,25 @@ const { generateAccessToken } = require('@adobe/aio-lib-core-auth')
3636

3737
async function main(params) {
3838
try {
39-
// Note: Will cache for 5 min
39+
// if the include-ims-credentials annotation is set, the library infers credentials from the Runtime params
40+
const token = await generateAccessToken(params)
41+
42+
// otherwise credentials can be passed manually
4043
const token = await generateAccessToken({
41-
clientId: params.IMS_CLIENT_ID,
42-
clientSecret: params.IMS_CLIENT_SECRET,
43-
orgId: params.IMS_ORG_ID,
44-
scopes: params.IMS_SCOPES,
44+
clientId: '<clientId>',
45+
clientSecret: '<clientSecret>',
46+
orgId: '<orgId>@AdobeOrg',
47+
scopes: ['<scope1>', '<scope2>', '..']
4548
})
49+
4650
console.log('Authentication successful:', token.access_token)
4751
} catch (error) {
4852
console.error('Authentication failed:', error)
4953
}
5054
}
5155
```
5256

53-
Note: The token is cached in the Runtime's container memory, a single Runtime action can run in multiple containers.
57+
Note: The token is cached for 5 minutes in the Runtime's container memory. A single Runtime action can run in multiple containers, meaning the cache is not shared across actions.
5458

5559
### Invalidating the Token Cache in a Runtime action
5660

src/constants.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
Copyright 2026 Adobe. All rights reserved.
3+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License. You may obtain a copy
5+
of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
Unless required by applicable law or agreed to in writing, software distributed under
7+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8+
OF ANY KIND, either express or implied. See the License for the specific language
9+
governing permissions and limitations under the License.
10+
*/
11+
12+
// support parameters set in the include-ims-credentials annotation
13+
export const IMS_OAUTH_S2S_INPUT = '__ims_oauth_s2s'
14+
export const IMS_ENV_INPUT = '__ims_env'

src/errors.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const E = ErrorWrapper(
3939

4040
// Error codes
4141
E('IMS_TOKEN_ERROR', 'Error calling IMS to get access token: %s')
42-
E('MISSING_PARAMETERS', 'Missing required parameters: %s')
42+
E('MISSING_PARAMETERS', 'Missing required parameters: %s. You may want to set the include-ims-credentials annotation.')
4343
E('BAD_CREDENTIALS_FORMAT', 'Credentials must be either an object or a stringified object')
4444
E('BAD_SCOPES_FORMAT', 'Scopes must be an array')
4545
E('GENERIC_ERROR', 'An unexpected error occurred: %s')

src/ims.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,23 @@ function getImsUrl (env) {
3333
*
3434
* @private
3535
* @param {object} params - Parameters to validate
36-
* @returns {object} Validated credentials object
37-
* @throws {Error} If any required parameters are missing
36+
* @returns {{ error, credentials }} Object with error (if any) and validated credentials object
3837
*/
3938
function getAndValidateCredentials (params) {
4039
if (!(typeof params === 'object' && params !== null && !Array.isArray(params))) {
41-
throw new codes.BAD_CREDENTIALS_FORMAT({
42-
sdkDetails: { paramsType: typeof params }
43-
})
40+
return {
41+
error: new codes.BAD_CREDENTIALS_FORMAT({
42+
sdkDetails: { paramsType: typeof params }
43+
})
44+
}
4445
}
4546

4647
if (params.scopes && !Array.isArray(params.scopes)) {
47-
throw new codes.BAD_SCOPES_FORMAT({
48-
sdkDetails: { scopesType: typeof params.scopes }
49-
})
48+
return {
49+
error: new codes.BAD_SCOPES_FORMAT({
50+
sdkDetails: { scopesType: typeof params.scopes }
51+
})
52+
}
5053
}
5154

5255
const credentials = {}
@@ -68,13 +71,13 @@ function getAndValidateCredentials (params) {
6871
}
6972

7073
if (missingParams.length > 0) {
71-
throw new codes.MISSING_PARAMETERS({
74+
return { error: new codes.MISSING_PARAMETERS({
7275
messageValues: missingParams.join(', '),
7376
sdkDetails: { clientId, orgId, scopes }
74-
})
77+
}) }
7578
}
7679

77-
return credentials
80+
return { credentials, error: null }
7881
}
7982

8083
/**

src/index.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ governing permissions and limitations under the License.
1010
*/
1111

1212
const { getAccessTokenByClientCredentials, getAndValidateCredentials } = require('./ims.js')
13-
const { codes, messages } = require('./errors.js')
1413
const { TTLCache } = require('@isaacs/ttlcache')
1514
const crypto = require('crypto')
1615

16+
// include-ims-credentials annotation input keys (keep in sync with src/constants.js)
17+
const IMS_OAUTH_S2S_INPUT = '__ims_oauth_s2s'
18+
const IMS_ENV_INPUT = '__ims_env'
19+
1720
// Token cache with TTL
1821
// Opinionated for now, we could make it configurable in the future if needed -mg
1922
const tokenCache = new TTLCache({ ttl: 5 * 60 * 1000 }) // 5 minutes in milliseconds
@@ -56,9 +59,21 @@ function invalidateCache () {
5659
* @throws {Error} If there's an error getting the access token
5760
*/
5861
async function generateAccessToken (params, imsEnv) {
59-
imsEnv = imsEnv || (ioRuntimeStageNamespace() ? 'stage' : 'prod')
62+
// integrate with the runtime environment and include-ims-credentials annotation
63+
imsEnv = imsEnv || params?.[IMS_ENV_INPUT] || (ioRuntimeStageNamespace() ? 'stage' : 'prod')
64+
65+
let credentials
6066

61-
const credentials = getAndValidateCredentials(params)
67+
// get parameters from params in priority otherwise try to load the credentials set to params.__ims_oauth_s2s by the annotation
68+
const fromParams = getAndValidateCredentials(params)
69+
credentials = fromParams.credentials
70+
if (fromParams.error) {
71+
const fromAnnotation = getAndValidateCredentials(params?.[IMS_OAUTH_S2S_INPUT])
72+
if (fromAnnotation.error) {
73+
throw fromParams.error // still throw original error
74+
}
75+
credentials = fromAnnotation.credentials
76+
}
6277

6378
const credAndEnv = { ...credentials, env: imsEnv }
6479

0 commit comments

Comments
 (0)