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

Implement authorisation in existing endpoints #84

Closed
gnarea opened this issue Apr 8, 2023 · 1 comment · Fixed by #103
Closed

Implement authorisation in existing endpoints #84

gnarea opened this issue Apr 8, 2023 · 1 comment · Fixed by #103
Assignees
Labels

Comments

@gnarea
Copy link
Member

gnarea commented Apr 8, 2023

As per the README.

The healthcheck, which isn't part of the RESTful API documented in the README, should continue to support anonymous requests.

@gnarea gnarea self-assigned this Apr 8, 2023
kodiakhq bot pushed a commit that referenced this issue Apr 10, 2023
Fixes #2.

High-level changes:

- Integrate [`mock-oauth2-server`](https://github.com/navikt/mock-oauth2-server) in development.
- Integrate fork of [`fastify-auth0-verify`](https://github.com/nearform/fastify-auth0-verify). See #82.

#84 will actually use `request.user` to enforce authorisation, so no endpoint is being updated to enforce authorisation here.

# Testing

This PR can be verified by creating the dummy route `GET /authn` as follows:

```diff
diff --git a/src/services/routes/healthcheck.routes.ts b/src/services/routes/healthcheck.routes.ts
index 7b7abe7..6cf48d3 100644
--- a/src/services/routes/healthcheck.routes.ts
+++ b/src/services/routes/healthcheck.routes.ts
@@ -20,5 +20,15 @@ export default function registerRoutes(
     },
   });
 
+  fastify.route({
+    method: ['GET'],
+    url: '/authn',
+    preValidation: fastify.authenticate,
+
+    async handler(request, reply): Promise<void> {
+      await reply.code(HTTP_STATUS_CODES.OK).send(request.user);
+    },
```

Then making requests to it as follows:

```http
### Make anonymous request
GET http://veraid-authority.default.10.103.177.106.sslip.io/authn

### Make authenticated request with invalid credentials
GET http://veraid-authority.default.10.103.177.106.sslip.io/authn
Authorization: Bearer INVALID_TOKEN

### Make authenticated request with valid credentials
GET http://veraid-authority.default.10.103.177.106.sslip.io/authn
Authorization: Bearer <VALID-TOKEN-HERE>
```

`<VALID-TOKEN-HERE>` can be obtained with:

```http
### Authenticate with authorisation server (client credentials)
POST http://mock-authz-server.default.10.103.177.106.sslip.io/default/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=admin@example.com&client_secret=s3cr3t
```
gnarea added a commit that referenced this issue Apr 10, 2023
This is groundwork for #84, as we need to use [Fastify encapsulation](https://www.fastify.io/docs/latest/Reference/Encapsulation/) to enforce authz.

Note that I also had to merge `configureFastify()` into `makeServer()` as we'll also need to more control over plugins (their execution order and the parameters we pass to them). It never really make sense to separate the two in the first place (I copied them from another project where we have multiple servers, so it makes sense there).
kodiakhq bot pushed a commit that referenced this issue Apr 11, 2023
This is groundwork for #84, as we need to use [Fastify encapsulation](https://www.fastify.io/docs/latest/Reference/Encapsulation/) to enforce authz.

Note that I also had to convert `configureFastify()` into something that just registers a "plugin", as we'll also need to more control over plugins (their execution order and the parameters we pass to them). I'm calling the new function `makeFastify()` for consistency with Fastify's style (for example, to initialise a Fastify _instance_, you call the default export from `fastify`).
@kodiakhq kodiakhq bot closed this as completed in #103 Apr 20, 2023
kodiakhq bot pushed a commit that referenced this issue Apr 20, 2023
Fixes #84.

# High-level changes

- Implement _super admin_ support by using an optional env var (`AUTHORITY_SUPERADMIN`) that specifies the JWT subject id of the super admin (i.e., their email address).
- **Existing API tests are now run as a super admin**.
- Update test suite for each endpoint to run authorisation checks with every type of user (using test util `testOrgRouteAuth()`).
- Anonymous users now get a `401` on any endpoint under `/orgs`.
- Regular members aren't allowed to update their own membership for security reasons: they shouldn't be allowed to change anything -- especially their user name. 
- Regular members aren't allowed to delete their own membership: I can't think of any legitimate use case for it, but I can think of things goes awry if the membership dataset for an organisation goes out of sync with the org's data sources.

# Notes

- Auth takes precedence over existence checks for security reasons. So, for example, no authenticated user could just request `GET /orgs/bbc.com` to check if `bbc.com` is registered:
  - A `403` will be returned regardless of whether `bbc.com` exists or not, if the current user isn't an admin of `bbc.com`. For example, if the user is a regular member of `bbc.com` or not even a member at all.
  - A `200` will be returned if the org exists and the user is an admin of `bbc.com`.
  - Super admins will get a `200` if the org exists or `404` if it doesn't.

# Testing

First off, you need an access token to make authenticated requests to anything under `/orgs`. To obtain one for the super admin (`admin@veraid.example`), run:

```http
### Authenticate with authorisation server (client credentials)
POST http://mock-authz-server.default.10.103.177.106.sslip.io/default/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=admin@veraid.example&client_secret=s3cr3t
```

Replace the email address above to impersonate any user -- even someone who's not a member of any org.

You can now make authenticated requests. For example:

```http
### Create org
POST http://veraid-authority.default.10.103.177.106.sslip.io/orgs
Authorization: Bearer <INSERT-ACCESS-TOKEN-HERE>
Content-Type: application/json

{
  "name": "example.com",
  "memberAccessType": "OPEN"
}

### Get org
GET http://veraid-authority.default.10.103.177.106.sslip.io/orgs/example.com
Authorization: Bearer <INSERT-ACCESS-TOKEN-HERE>
```
@github-actions
Copy link

🎉 This issue has been resolved in version 1.12.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Development

Successfully merging a pull request may close this issue.

1 participant