Skip to content

Commit

Permalink
Merge pull request #275 from camunda/bearer-token-authorization
Browse files Browse the repository at this point in the history
feat(authorization): add bearer token authorization
  • Loading branch information
jwulf authored Nov 14, 2024
2 parents 864a507 + f7d1ff3 commit c427878
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 3 deletions.
33 changes: 33 additions & 0 deletions src/__tests__/oauth/OAuthProvider.unit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -613,4 +613,37 @@ describe('OAuthProvider', () => {
expect(res).toBeTruthy()
})
})

it('Can use Bearer Token Auth as a strategy', async () => {
const server = http.createServer((req, res) => {
const authHeader = req.headers['authorization']

if (!authHeader || authHeader !== 'Bearer mysecrettoken') {
res.statusCode = 401
res.setHeader('WWW-Authenticate', 'Bearer realm="example"')
res.end('Access denied')
} else {
res.end('Access granted')
}
})

server.listen(3033)

const oAuthProvider = constructOAuthProvider({
CAMUNDA_AUTH_STRATEGY: 'BEARER',
CAMUNDA_OAUTH_TOKEN: 'mysecrettoken',
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any)
const token = await oAuthProvider.getToken('ZEEBE')
await got
.get('http://localhost:3033', {
headers: {
Authorization: 'Bearer ' + token,
},
})
.then((res) => {
server.close()
expect(res).toBeTruthy()
})
})
})
13 changes: 10 additions & 3 deletions src/lib/Configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ const getMainEnv = () =>
type: 'string',
optional: true,
},
/** The OAuth token (used for CAMUNDA_AUTH_STRATEGY "BEARER") */
CAMUNDA_OAUTH_TOKEN: {
type: 'string',
optional: true,
},
/** Optional scope parameter for OAuth (needed by some OIDC) */
CAMUNDA_TOKEN_SCOPE: {
type: 'string',
Expand Down Expand Up @@ -195,7 +200,7 @@ const getMainEnv = () =>
},
CAMUNDA_AUTH_STRATEGY: {
type: 'string',
choices: ['BASIC', 'OAUTH', 'NONE'],
choices: ['BASIC', 'OAUTH', 'BEARER', 'NONE'],
default: 'OAUTH',
},
})
Expand Down Expand Up @@ -367,8 +372,9 @@ const getEnv = () => ({

// Helper type for enforcing array contents to match an object's keys
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type EnforceArrayContent<T, K extends keyof any> =
T extends Array<K> ? T : never
type EnforceArrayContent<T, K extends keyof any> = T extends Array<K>
? T
: never

// Function to create a complete keys array, enforcing completeness at compile time
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -396,6 +402,7 @@ export const CamundaEnvironmentVariableDictionary =
'CAMUNDA_OPTIMIZE_OAUTH_AUDIENCE',
'CAMUNDA_OAUTH_DISABLED',
'CAMUNDA_OAUTH_URL',
'CAMUNDA_OAUTH_TOKEN',
'CAMUNDA_SECURE_CONNECTION',
'CAMUNDA_TASKLIST_BASE_URL',
'CAMUNDA_TASKLIST_OAUTH_AUDIENCE',
Expand Down
4 changes: 4 additions & 0 deletions src/lib/ConstructOAuthProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import debug from 'debug'

import { NullAuthProvider, OAuthProvider } from '../oauth'
import { BasicAuthProvider } from '../oauth/lib/BasicAuthProvider'
import { BearerAuthProvider } from '../oauth/lib/BearerAuthProvider'

import { CamundaPlatform8Configuration } from './Configuration'

Expand All @@ -20,6 +21,9 @@ export function constructOAuthProvider(config: CamundaPlatform8Configuration) {
if (config.CAMUNDA_AUTH_STRATEGY === 'BASIC') {
trace(`Using Basic Auth`)
return new BasicAuthProvider({ config })
} else if (config.CAMUNDA_AUTH_STRATEGY === 'BEARER') {
trace(`Using Bearer Token`)
return new BearerAuthProvider({ config })
} else {
trace(`Using OAuth`)
return new OAuthProvider({ config })
Expand Down
34 changes: 34 additions & 0 deletions src/oauth/lib/BearerAuthProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { debug } from 'debug'

import {
CamundaEnvironmentConfigurator,
CamundaPlatform8Configuration,
DeepPartial,
RequireConfiguration,
} from '../../lib'
import { IOAuthProvider } from '../index'

import { TokenGrantAudienceType } from './IOAuthProvider'

export class BearerAuthProvider implements IOAuthProvider {
private bearerToken: string

constructor(options?: {
config?: DeepPartial<CamundaPlatform8Configuration>
}) {
const config = CamundaEnvironmentConfigurator.mergeConfigWithEnvironment(
options?.config ?? {}
)

this.bearerToken = RequireConfiguration(
config.CAMUNDA_OAUTH_TOKEN,
'CAMUNDA_OAUTH_TOKEN'
)
}

public async getToken(audienceType: TokenGrantAudienceType): Promise<string> {
debug(`Token request for ${audienceType}`)

return Promise.resolve(this.bearerToken)
}
}

0 comments on commit c427878

Please sign in to comment.