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

Switch hashes to SHA-256 and implement token limitations #1263

Merged
merged 7 commits into from
May 15, 2024

Conversation

a3957273
Copy link
Member

@a3957273 a3957273 commented May 8, 2024

No description provided.

@@ -10,12 +11,37 @@ export const TokenScope = {
export type TokenScopeKeys = (typeof TokenScope)[keyof typeof TokenScope]

export const TokenActions = {
ImageRead: 'image:read',
ModelRead: 'model:read',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These all seem very similar to the permissions defined in the authorisation actions. My concern here is duplication and confusion in how they are similar but not the same- eg in the authorisation actions there's access_request:create and access_request:view and in this file you've defined access_request:write and access_request:read.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid duplication these token actions should be exposed via the API so clients know what token actions are available to them

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid having to have a separate mapping to authorisation actions and to improve readability, each of these definitions should include an array of the authorisation actions they contain as well as the existing name of the token action eg 'model:read'

@@ -110,22 +111,68 @@ export async function getTokenFromAuthHeader(header: string) {
return token
}

export async function validateTokenForModel(token: TokenDoc, modelId: string, action: TokenActionsKeys) {
export async function validateTokenForUse(token: TokenDoc | undefined, action: TokenActionsKeys): Promise<Response> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could token be undefined when the only place this method is used is in an if statement that checks if it's defined? Additionally, why should lack of a token just grant you access?

return Promise.all(
schemas.map(async (schema) => {
// Is this a constrained user token.
if (user.token && (await validateTokenForUse(user.token, ActionLookup[action]))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateTokenForUse() is used in if statement and returns an object not a boolean? What's the point in the method returning information if you're not going to use it?

@@ -133,6 +158,15 @@ export class BasicAuthorisationConnector {
[ReleaseAction.View]: ModelAction.View,
}

// Is this a constrained user token.
if (user.token?.actions && !user.token.actions.includes(ActionLookup[action])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use validateTokenForUse() in places like this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you don't check the model restriction on the token?

@@ -77,6 +80,15 @@ export class BasicAuthorisationConnector {
async models(user: UserInterface, models: Array<ModelDoc>, action: ModelActionKeys): Promise<Array<Response>> {
return Promise.all(
models.map(async (model) => {
// Is this a constrained user token.
if (user.token && (await validateTokenForModel(user.token, model.id, ActionLookup[action]))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateTokenForModel() no longer returns a boolean?

}

export async function validateTokenForModel(
token: TokenDoc | undefined,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as with the other method- the sole use of this function already checks for the token's presence and why should the lack of a token just grant access?

success: true,
}
}

if (token.scope === 'models' && !token.modelIds.includes(modelId)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the 'enum' here

})
} else {
throw new Error('Unexpected hash type: ' + this.hashMethod)
}
})

TokenSchema.methods.compareToken = function compareToken(candidateToken: string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could/ should this function be in the service? Are there unit tests for this as it's a very important function?

@a3957273 a3957273 requested a review from JR40159 May 15, 2024 12:22
@a3957273 a3957273 merged commit b80398e into main May 15, 2024
14 checks passed
@a3957273 a3957273 deleted the feature/token-auth branch May 15, 2024 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants