Skip to content

Commit

Permalink
Merge pull request #97 from AckeeCZ/fix/auth
Browse files Browse the repository at this point in the history
Fix/auth
  • Loading branch information
cermakjiri authored Nov 18, 2024
2 parents 2b2c90f + a1a8d6f commit c0098e6
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 103 deletions.
67 changes: 20 additions & 47 deletions docs/web/src/pages/en/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,36 @@ description: How to authenticate in Lokse
layout: ../../layouts/MainLayout.astro
---

The last version of Google Spreadsheets API requires us to be authenticated to allow fetching spreadsheet data 🔑
In order to fetch spreadsheet via `lokse update` command, you need to authenticate first. `lokse` uses [**Application default credential**](https://cloud.google.com/docs/authentication/provide-credentials-adc) – sign-in just with your Google account or provide service account.

There are three options for authentication: Service Account or API key. For each of these options we have to define some values as environment variables.
## Authenticate `lokse` locally (in your CLI):

## Environment variables
1. Install `gcloud` first:

We have practically two ways of how to define environment variables containing API key or Service Account credentials
https://cloud.google.com/sdk/docs/install

Use it before the command like
2. Sign-in with Google:

```sh
$ LOKSE_SERVICE_ACCOUNT_EMAIL=this_is_account_email LOKSE_PRIVATE_KEY=this_is_the_private_key lokse update
```

or use a more flexible and handy way of keeping variables inside the `.env.local` file. Create the file if you don't have it yet and put your variables into it like

```
LOKSE_SERVICE_ACCOUNT_EMAIL=this_is_account_email
LOKSE_PRIVATE_KEY=this_is_the_private_key
```

then you'll be able to run

```sh
$ lokse update
```
```sh
gcloud auth application-default login --scopes=openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/spreadsheets,https://www.googleapis.com/auth/drive.file
```

> For the sake of security reasons **Never check your API keys / secrets into version control**. That means you should **not forget to add `.env.local` into the `.gitignore`**.
3. Fetch spreadsheets:

## Service Account
```sh
lokse update
```

Currently the best option for authentication is to create a Service account (if you don't have any, follow [the instructions here](https://theoephraim.github.io/node-google-spreadsheet/#/getting-started/authentication?id=service-account)) and then setup at least read permissions for your account in the spreadsheet.
4. In case of getting quote project warning:

Since every Service account contains email adress just click the "Share" button at top right corner of the spreadsheet and add your Service account email there.
```sh
gcloud auth application-default set-quota-project <project-name>
```

Once you have the Service account created, you should have its client email and private key. It looks smilar to this
## Authentication `lokse` in CI pipeline:

```
"client_email": "localize-with-spreadsheet@localize-with-spreadsheet.iam.gserviceaccount.com",
"private_key": "-----BEGIN PRIVATE KEY-----\nAnd_here_is_a_long_text_of_random_characters_that_defines_the_private_key\n-----END PRIVATE KEY-----\n",
```

Take these two values, put them into `LOKSE_SERVICE_ACCOUNT_EMAIL` and `LOKSE_PRIVATE_KEY` variables using one of two ways [described above](#environment-variables) and there you go, fetching data from spreadsheet should work now.

## API key

For read only access, we're good with usage of API key, if you don't have any, follow [the instructions here](https://theoephraim.github.io/node-google-spreadsheet/#/getting-started/authentication?id=api-key) to create one.
https://cloud.google.com/docs/authentication/provide-credentials-adc:

Then define the variable `LOKSE_API_KEY=this_is_your_api_key` and then if the key is valid fetching data should work for you.

Using API key instead of Service account has one important limitation: You spreadsheet must set permissions to be visible for everyone in the Internet.

## Application default credential

If none of those environment variables have been provided, `lokse` fallbacks to [application default credential authentication](https://cloud.google.com/docs/authentication/provide-credentials-adc).
Don't forget to login first with appropriate scopes:

```bash
gcloud auth application-default login --scopes=openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/spreadsheets,https://www.googleapis.com/auth/drive.file
```sh
export GOOGLE_APPLICATION_CREDENTIALS="SERVICE_ACCOUNT_KEY_PATH"
```
34 changes: 0 additions & 34 deletions packages/core/src/reader/__tests__/spreadsheet-reader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,40 +35,6 @@ describe('SpreadsheetReader', () => {
GoogleSpreadsheetMock.mockClear();
});

afterEach(() => {
delete process.env.LOKSE_API_KEY;
delete process.env.LOKSE_SERVICE_ACCOUNT_EMAIL;
delete process.env.LOKSE_PRIVATE_KEY;
});

it('uses service account if available', async () => {
const private_key = 'this-is-dummy-private-key';
const client_email = 'this-is@dummy-email';

process.env.LOKSE_SERVICE_ACCOUNT_EMAIL = client_email;
process.env.LOKSE_PRIVATE_KEY = private_key;

const reader = new SpreadsheetReader('test-sheet-id', new WorksheetReader('*'), noPlugins);

const client = await reader.authenticate();

// @ts-expect-error private property
expect(client._clientId).toEqual(client_email);
// @ts-expect-error private property
expect(client._clientSecret).toEqual(private_key);
});

it('uses api key if available', async () => {
const dummyApiKey = 'dummy-api-key';
process.env.LOKSE_API_KEY = dummyApiKey;

const reader = new SpreadsheetReader('test-sheet-id', new WorksheetReader('*'), noPlugins);

const client = await reader.authenticate();

expect(client.apiKey).toEqual(dummyApiKey);
});

it('throw if service account nor api key found', async () => {
const reader = new SpreadsheetReader('test-sheet-id', new WorksheetReader('*'), noPlugins);

Expand Down
22 changes: 2 additions & 20 deletions packages/core/src/reader/spreadsheet-reader.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable camelcase */
import { GoogleSpreadsheet } from 'google-spreadsheet';
import { GoogleAuth, JWT } from 'google-auth-library';
import { GoogleAuth } from 'google-auth-library';

import Line from '../line';
import { FatalError, getErrorMessage } from '../errors';
Expand Down Expand Up @@ -36,25 +37,6 @@ export class SpreadsheetReader {
}

createAuthClient() {
const { LOKSE_API_KEY, LOKSE_SERVICE_ACCOUNT_EMAIL, LOKSE_PRIVATE_KEY } = process.env;

if (LOKSE_SERVICE_ACCOUNT_EMAIL && LOKSE_PRIVATE_KEY) {
this.logger.log('🔑 Authenticating with service account...');

const jwt = new JWT({
clientId: LOKSE_SERVICE_ACCOUNT_EMAIL,
clientSecret: LOKSE_PRIVATE_KEY,
});

return new GoogleAuth({ authClient: jwt });
}

if (LOKSE_API_KEY) {
this.logger.log('🔑 Authenticating with API key...');

return new GoogleAuth({ apiKey: LOKSE_API_KEY });
}

this.logger.log('🔑 Authenticating with Application Default Credentials...');

return new GoogleAuth({
Expand Down
3 changes: 1 addition & 2 deletions packages/core/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "lib",
"rootDir": "src",
"skipLibCheck": true
"rootDir": "src"
},
"include": [
"src/**/*",
Expand Down

0 comments on commit c0098e6

Please sign in to comment.