Skip to content
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
51 changes: 7 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,59 +134,22 @@ $ firebase deploy --only functions

Can be called to create a custom authentication token. Has to be called via **`POST`**.

There are two authentication modes implemented: `ip` and `flightnet`.
The following authentication modes are implemented: `static`, `guest_token` and `kiosk_token`.

#### Mode *ip*
#### Mode *static*

Returns a token if the request comes from one of the allowed IP addresses. The allowed addresses can be configured
via the configuration property `auth.ips`. The following example sets the IP addresses `109.205.200.60` and
`77.59.197.122` as allowed IP addresses.

```
$ firebase functions:config:set auth.ips="109.205.200.60,77.59.197.122"
```

Request example:
```
$ curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"mode": "ip"}' \
https://europe-west1-<PROJECT_ID>.cloudfunctions.net/auth
```

#### Mode *flightnet*

Returns a token if the given credentials are valid Flightnet credentials. You have to send the flightnet company,
the username and the password in the request body.
Returns a token if the given username and password match one of the configured static credentials. The credentials
are configured via the `AUTH_STATIC_CREDENTIALS` environment variable as a comma-separated list of `username:password`
pairs (e.g. `AUTH_STATIC_CREDENTIALS="foo:bar,admin:12345"`). If no credentials are configured, authentication always
fails.

Request example:

```
$ curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"mode": "flightnet", "company": "<FLIGHTNET_COMPANY>", "username": "<FLIGHTNET_USERNAME>", "password": "<FLIGHTNET_PASSWORD>"}' \
https://europe-west1-<PROJECT_ID>.cloudfunctions.net/auth
```

##### Test credentials #####

For testing purposes, test credentials can be set for this mode. If test credentials are set, authentication will
**never** be delegated to the Flightnet authentication service.

Set the test credentials in the function config:
```
$ firebase functions:config:set auth.testcredentials.username="foo"
$ firebase functions:config:set auth.testcredentials.password="bar"
```

Request example (`company` not needed in request body):
```
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"mode": "flightnet", "username": "foo", "password": "bar"}' \
-d '{"mode": "static", "username": "<USERNAME>", "password": "<PASSWORD>"}' \
https://europe-west1-<PROJECT_ID>.cloudfunctions.net/auth
```

Expand Down
2 changes: 1 addition & 1 deletion cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const login = (username, password) => {
cy.request('POST', 'https://europe-west1-cypress-testing.cloudfunctions.net/auth', {
mode: 'flightnet',
mode: 'static',
username,
password
}).then((response) => {
Expand Down
41 changes: 0 additions & 41 deletions functions/auth/modes/flightnet/flightnet.js

This file was deleted.

112 changes: 0 additions & 112 deletions functions/auth/modes/flightnet/index.spec.js

This file was deleted.

4 changes: 2 additions & 2 deletions functions/auth/modes/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use strict';

const flightnet = require('./flightnet');
const staticMode = require('./static');
const guest_token = require('./guest_token');
const kiosk_token = require('./kiosk_token');

module.exports = {
flightnet: flightnet,
static: staticMode,
guest_token: guest_token,
kiosk_token: kiosk_token
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use strict';

const flightnet = require('./flightnet');
const requestHelper = require('../../util/requestHelper');

const parseStaticCredentials = () => {
Expand All @@ -23,13 +22,10 @@ module.exports = req => {
const username = requestHelper.requireBodyProperty(req, 'username');
const password = requestHelper.requireBodyProperty(req, 'password');

if (staticCredentials) {
const match = staticCredentials.find(login => login.username === username && login.password === password);
const uid = match ? username : null;
return Promise.resolve(uid);
} else {
const company = requestHelper.requireBodyProperty(req, 'company');
return flightnet.passwordCheck(company, username, password)
.then(success => success ? username : null)
if (!staticCredentials) {
return Promise.resolve(null);
}

const match = staticCredentials.find(login => login.username === username && login.password === password);
return Promise.resolve(match ? username : null);
};
65 changes: 65 additions & 0 deletions functions/auth/modes/static/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use strict';

describe('functions', () => {
describe('auth', () => {
describe('modes', () => {
describe('static', () => {
const loadStatic = (credentials) => {
jest.resetModules();
if (credentials) {
process.env.AUTH_STATIC_CREDENTIALS = credentials;
} else {
delete process.env.AUTH_STATIC_CREDENTIALS;
}
return require('.');
};

afterEach(() => {
delete process.env.AUTH_STATIC_CREDENTIALS;
});

it('should throw a ClientError if `username` is missing in request body', () => {
const staticMode = loadStatic('alice:pw1');
const request = { body: { password: 'pw1' } };
return expect(() => staticMode(request)).toThrow('Required property `username` missing in request body.');
});

it('should throw a ClientError if `password` is missing in request body', () => {
const staticMode = loadStatic('alice:pw1');
const request = { body: { username: 'alice' } };
return expect(() => staticMode(request)).toThrow('Required property `password` missing in request body.');
});

it('returns the username when the first static credential matches', () => {
const staticMode = loadStatic('alice:pw1,bob:pw2');
const request = { body: { username: 'alice', password: 'pw1' } };
return expect(staticMode(request)).resolves.toEqual('alice');
});

it('returns the username when the second static credential matches', () => {
const staticMode = loadStatic('alice:pw1,bob:pw2');
const request = { body: { username: 'bob', password: 'pw2' } };
return expect(staticMode(request)).resolves.toEqual('bob');
});

it('returns null when the password is wrong for a known username', () => {
const staticMode = loadStatic('alice:pw1,bob:pw2');
const request = { body: { username: 'alice', password: 'wrong' } };
return expect(staticMode(request)).resolves.toBeNull();
});

it('returns null when the username is unknown', () => {
const staticMode = loadStatic('alice:pw1,bob:pw2');
const request = { body: { username: 'charlie', password: 'pw1' } };
return expect(staticMode(request)).resolves.toBeNull();
});

it('returns null when no static credentials are configured', () => {
const staticMode = loadStatic(null);
const request = { body: { username: 'alice', password: 'pw1' } };
return expect(staticMode(request)).resolves.toBeNull();
});
});
});
});
});
Loading
Loading