Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(authorization): add bearer token authorization #275

Merged
merged 1 commit into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
}
}
Loading