Created
January 9, 2020 13:46
-
-
Save iseebi/4d21bf68c79bc020ea3515693676a35f to your computer and use it in GitHub Desktop.
コマンドラインでGoogle APIのOAuthを通すクラス
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* tslint:disable:no-console */ | |
import * as fs from "fs"; | |
import {Credentials, OAuth2Client} from "google-auth-library" | |
import {google} from "googleapis"; | |
import * as path from "path"; | |
import {createInterface} from "readline"; | |
import {ReadLine} from "readline"; | |
interface IClientID { | |
client_id: string | |
client_secret: string | |
} | |
interface IClientIDFile { | |
installed: IClientID | |
} | |
const CALLBACK_URL = 'urn:ietf:wg:oauth:2.0:oob'; | |
export class Authenticator { | |
private readonly baseDir: string; | |
private readonly scopes: string[]; | |
private readonly tokenFileName: string; | |
private readonly clientIdFileName: string; | |
private oAuth2Client?: OAuth2Client; | |
private readline?: ReadLine; | |
constructor(baseDir: string, scopes: string[]) { | |
this.baseDir = baseDir; | |
this.scopes = scopes; | |
this.tokenFileName = path.join(this.baseDir, 'token.json'); | |
this.clientIdFileName = path.join(this.baseDir, 'client_id.json'); | |
} | |
public async authenticateAsync(): Promise<OAuth2Client> { | |
let token = await this.readTokenAsync(); | |
if (!token) { | |
token = await this.getNewTokenAsync(); | |
} | |
const client = await this.getClientAsync(); | |
client.setCredentials(token); | |
return client; | |
} | |
private async getClientAsync(): Promise<OAuth2Client> { | |
if (!this.oAuth2Client) { | |
const clientIdFile = await this.readClientIdAsync(); | |
const clientId = clientIdFile.installed; | |
this.oAuth2Client = new google.auth.OAuth2(clientId.client_id, clientId.client_secret, CALLBACK_URL); | |
} | |
return this.oAuth2Client; | |
} | |
private async getNewTokenAsync(): Promise<Credentials> { | |
const client = await this.getClientAsync(); | |
const authUrl = client.generateAuthUrl({ | |
access_type: 'offline', | |
scope: this.scopes | |
}); | |
console.log('Authorize this app by visiting this url: ', authUrl); | |
const code = await this.askAsync('Enter the code from that page here: '); | |
const token = await client.getToken(code); | |
await this.writeTokenAsync(token.tokens); | |
return token.tokens; | |
} | |
private async readClientIdAsync(): Promise<IClientIDFile> { | |
const file = await fs.promises.readFile(this.clientIdFileName, {encoding: "utf8"}); | |
return JSON.parse(file); | |
} | |
private async writeTokenAsync(token: Credentials): Promise<void> { | |
await fs.promises.writeFile(this.tokenFileName, JSON.stringify(token)); | |
} | |
private async readTokenAsync(): Promise<Credentials|undefined> { | |
try { | |
await fs.promises.stat(this.tokenFileName); | |
const file = await fs.promises.readFile(this.tokenFileName, {encoding: "utf8"}); | |
return JSON.parse(file); | |
} | |
catch(e) { | |
return undefined; | |
} | |
} | |
private getReadLine(): ReadLine { | |
if (!this.readline) { | |
this.readline = createInterface({ | |
input: process.stdin, | |
output: process.stdout, | |
}); | |
} | |
return this.readline; | |
} | |
private askAsync(query: string): Promise<string> { | |
const rl = this.getReadLine(); | |
return new Promise((resolve) => { | |
rl.question(query, (input) => { | |
rl.close(); | |
resolve(input) | |
}); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment