Skip to content

Commit

Permalink
Merge pull request #1654 from balena-io/enforces-login-with-auth-perm…
Browse files Browse the repository at this point in the history
…ission

Enforces login with auth permission
  • Loading branch information
flowzone-app[bot] authored Jun 5, 2024
2 parents 4c7e5b8 + 4e453b1 commit 4d15b35
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/features/auth/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { errors, sbvrUtils } from '@balena/pinejs';
import { comparePassword, findUser } from '../../infra/auth/auth.js';
import { loginUserXHR } from '../../infra/auth/jwt.js';
import { captureException } from '../../infra/error-handling/index.js';
import { permissions } from '@balena/pinejs';

import type { SetupOptions } from '../../index.js';

Expand All @@ -28,6 +29,12 @@ export const login =
if (!matches) {
throw new BadRequestError('Current password incorrect.');
}

const userPermissions = await permissions.getUserPermissions(user.id);
if (!userPermissions.includes('auth.credentials_login')) {
throw new BadRequestError('User not allowed to login.');
}

if (onLogin) {
await onLogin(user, tx);
}
Expand Down
51 changes: 51 additions & 0 deletions test/04_session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import { supertest } from './test-lib/supertest.js';
import * as versions from './test-lib/versions.js';
import type { Device } from './test-lib/fake-device.js';
import type { Application } from '../src/balena-model.js';
import {
assignUserRole,
revokeUserRole,
} from '../src/infra/auth/permissions.js';
import { permissions as pinePermissions, sbvrUtils } from '@balena/pinejs';
const { api } = sbvrUtils;

const atob = (x: string) => Buffer.from(x, 'base64').toString('binary');
const parseJwt = (t: string) => JSON.parse(atob(t.split('.')[1]));
Expand Down Expand Up @@ -300,6 +306,51 @@ export default () => {

await supertest(accessToken).get('/actor/v1/whoami').expect(401);
});

it('/login_ returns a 401 error if user does not have auth.credentials_login permission', async function () {
const user = (await supertest(admin).get('/user/v1/whoami').expect(200))
.body;

let role = await api.Auth.get({
resource: 'role',
passthrough: {
req: pinePermissions.rootRead,
},
id: {
name: 'default-user',
},
options: {
$select: 'id',
},
});

expect(role).to.have.property('id').that.is.a('number');
role = role as { id: number };

await sbvrUtils.db.transaction(async (tx) => {
await revokeUserRole(user.id, role.id, tx);
});

await supertest()
.post('/login_')
.send({
username: SUPERUSER_EMAIL,
password: SUPERUSER_PASSWORD,
})
.expect(401);

await sbvrUtils.db.transaction(async (tx) => {
await assignUserRole(user.id, role.id, tx);
});

await supertest()
.post('/login_')
.send({
username: SUPERUSER_EMAIL,
password: SUPERUSER_PASSWORD,
})
.expect(200);
});
});
});
};

0 comments on commit 4d15b35

Please sign in to comment.