1.2.9 • Published 6 days ago

@urbaninfrastructure/api-auth-sdk v1.2.9

Weekly downloads
-
License
ISC
Repository
github
Last release
6 days ago

@urbaninfrastructure/api-auth-sdk

> TODO: description

External request ACL validation

Import from /nestjs submodule in nestjs project, and from /express in others.

In frontend/web projects pure functions and interfaces can be imported from root module.

NestJS

Split ACL

import { AuthorizedResource, AuthorizedAction } from '@urbaninfrastructure/api-auth-sdk/nestjs'

// Decorate a controller, preferably using typed enums
@AuthorizedResource('fleet', 'vehicle')
@Controller()
class Controller {
    @Get('/edit')
    // Decorate a function with the allowed action
    @AuthorizedAction('update')
    async editResource() { ... }

    @Get('/other/edit')
    // Nested resource, first argument is nested resource, second is action
    @AuthorizedAction('other', 'update')
    async editOtherResource() { ... }
}

Object ACL

import { Authorized } from '@urbaninfrastructure/api-auth-sdk/nestjs'

@Controller()
class Controller {
    @Get('/edit')
    // Decorate function with full acl definition
    @Authorized({ product: 'fleet', resource: 'vehicle', action: 'update' })
    async editResource() { ... }
}

Object ACL, combinatorics

Arbitrary combinations using AclCombination interface can be supplied in order to validate complex acl definitions

@Authorized({
    and: [
        { is: { product: 'fleet', resource: 'vehicle', action: 'update' } },
        { is: { product: 'fleet', resource: 'trip', action: 'any' } },
        {
            not: [
                { is: toAcl('fleet', 'user', 'create') }
            ]
        }
    ]
})

See the @Authorized decorator function docs too.

Get authenticated administrator and their permissions

import {
    AclCandidate, Admin, Authorized, Permissions
} from '@urbaninfrastructure/api-auth-sdk/nestjs'

@Controller()
class Controller {
    @Get('/path')
    @Authorized({ product: 'fleet', resource: 'vehicle', action: 'any' })
    async pathHandler(
        @Admin() admin: AdministratorEntity,
        @Permissions() permissions: AclCandidate[],
    ) {
        console.log(admin)
        // { id: 'adm_1...', email: 'my@email.com', ... }
        console.log(permissions)
        // [ { product: 'fleet', owner: 'oslobysykkel', resource: 'vehicle', action: 'any' } ]
    }
}

AclOwner decorator

If the Owner (system id) isn't in a well-known location in the request (systemId or metaSystemId), use @AuthorizedOwner() to help locate it. Can also be used to specify "any" owner.

import {
    AuthorizedOwner, AuthorizedAction, AuthorizedResource
} from '@urbaninfrastructure/api-auth-sdk/nestjs'

@AuthorizedResource('vehicle')
@Controller
class Controller {
    @Get('/path')
    @AuthorizedOwner((req) => req.params.ownerId)
    @AuthorizedAction('read')
    async readVehicle() { ... }
}

Custom / express/sequelize

Provided middleware

import { reqHasAcl, toAcl, expressAuthorized } from '@urbaninfrastructure/api-auth-sdk/express'

router.use(expressAuthorized)

function hasPermission(req: Request, owner: string, resource: AclResource, action: AclAction): bool {
    return reqHasAcl(req, toAcl('fleet', owner, resource, action))
}

function onRequest(req: Request) {
    if (!hasPermission(req, req.systemId, 'vehicle', 'read')) {
        return null
    }
}

Custom

// Server (f.ex. core):
import {
    authenticateExternalRequest, authorizeAdministrator, toAcl
} from '@urbaninfrastructure/api-auth-sdk/express'

function onRequest(req: Request) {
    // Make sure req has cookies/headers (ie. express's cookie middleware)
    /// authenticateExternalRequest throws UnauthorizedError if token is invalid
    const jwtToken = authenticateExternalRequest(req)
    const result = authorizeAdministrator(jwtToken.sub, toAcl('fleet', systemId, 'vehicle', 'read'))
    // alternative:
    const result = authorizeAdministrator(jwtToken.sub, { product: 'fleet', owner: systemId, resource: 'vehicle', action: 'read' })
    // or an AclCombination:
    const result = authorizeAdministrator(jwtToken.sub, { and: [ { is: toAcl(...) }, { is: toAcl(...) } ] })

    if (!result.allowed) {
        throw new Error('unauthorized', result.missedAcls)
    }
}

Internal request usage

// Client:
import { getRequestToken, ApiJwtAudience } from '@urbaninfrastructure/api-auth-sdk/nestjs'
const token = getRequestToken(ApiJwtAudience.CORE)
doRequest(coreUrl, headers: { Authorization: `Bearer ${token}` })

// Server (nestjs)
import { InternalAuth } from '@urbaninfrastructure/api-auth-sdk/nestjs'

@Module({
    providers: [
        {
            provide: APP_GUARD,
            useClass: InternalAuth,
        },
    ],
})
export class AppModule {}

// Server (f.ex. in core):
import { authenticateInternalRequest } from '@urbaninfrastructure/api-auth-sdk/express'

function onRequest(req: Request) {
    const authMetadata = authenticateInternalRequest(req)
    console.log(`Requesting: ${authMetadata.requestingClient}`)
    console.log(`System id: ${authMetadata.urbanSharingSystemId}`)
}
1.2.9

6 days ago

1.2.8

9 days ago

1.2.7-dev.0

9 days ago

1.2.6

20 days ago

1.2.6-dev.0

23 days ago

1.2.5

24 days ago

1.2.5-dev.0

25 days ago

1.2.4

27 days ago

1.2.3

30 days ago

1.2.2

30 days ago

1.2.0

1 month ago

1.2.1

1 month ago

1.1.1

2 months ago

1.1.0

2 months ago

1.0.1

2 months ago

1.1.0-alpha.9

2 months ago

1.1.0-alpha.7

2 months ago

1.1.0-alpha.8

2 months ago

1.1.0-alpha.2

2 months ago

1.1.0-alpha.0

2 months ago

1.1.0-alpha.6

2 months ago

1.1.0-alpha.3

2 months ago

1.1.0-alpha.4

2 months ago

1.0.0

2 months ago

0.1.30

2 months ago

0.1.31

2 months ago

0.1.32

2 months ago

0.1.33

2 months ago

0.1.34

2 months ago

0.1.35

2 months ago

0.1.36

2 months ago

0.1.29

2 months ago

0.1.27

2 months ago

0.1.28

2 months ago

0.1.27-dev.0

2 months ago

0.1.10

3 months ago

0.1.11

3 months ago

0.1.12

3 months ago

0.1.13

3 months ago

0.1.14

3 months ago

0.1.15

3 months ago

0.1.9-dev.0

3 months ago

0.1.9

3 months ago

0.1.13-alpha.0

3 months ago

0.1.20

3 months ago

0.1.21

2 months ago

0.1.22

2 months ago

0.1.24

2 months ago

0.1.25

2 months ago

0.1.26

2 months ago

0.1.16

3 months ago

0.1.17

3 months ago

0.1.18

3 months ago

0.1.19

3 months ago

0.1.8-dev.0

3 months ago

0.1.3-dev.0

3 months ago

0.1.1-dev.0

3 months ago

0.1.6-dev.0

3 months ago

0.1.4-dev.0

3 months ago

0.1.2-dev.0

3 months ago

0.1.7-dev.0

3 months ago

0.1.5-dev.0

3 months ago

0.1.0-dev.0

3 months ago

0.0.5-dev.38

3 months ago

0.0.5-dev.37

3 months ago

0.0.5-dev.36

4 months ago

0.0.5-dev.35

4 months ago

0.0.5-dev.34

4 months ago

0.0.5-dev.33

4 months ago

0.0.5-dev.29

4 months ago

0.0.5-dev.32

4 months ago

0.0.5-dev.30

4 months ago

0.0.5-dev.31

4 months ago

0.0.5-dev.28

6 months ago

0.0.5-dev.27

6 months ago

0.0.5-dev.26

6 months ago

0.0.5-dev.25

6 months ago

0.0.5-dev.24

6 months ago

0.0.5-dev.23

6 months ago

0.0.5-dev.22

6 months ago

0.0.5-dev.21

6 months ago

0.0.5-dev.20

6 months ago

0.0.5-dev.19

6 months ago

0.0.5-dev.17

6 months ago

0.0.5-dev.16

6 months ago

0.0.5-dev.15

6 months ago

0.0.5-dev.14

6 months ago

0.0.5-dev.13

6 months ago

0.0.5-dev.12

6 months ago

0.0.5-dev.11

6 months ago

0.0.5-dev.10

6 months ago

0.0.5-dev.8

6 months ago

0.0.5-dev.7

6 months ago

0.0.5-dev.6

6 months ago

0.0.5-dev.5

6 months ago

0.0.5-dev.4

6 months ago

0.0.5-dev.3

6 months ago

0.0.5-dev.2

6 months ago