UNPKG

4.82 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const utils_fs_1 = require("@ionic/utils-fs");
4const utils_network_1 = require("@ionic/utils-network");
5const crypto = require("crypto");
6const http = require("http");
7const path = require("path");
8const qs = require("querystring");
9const constants_1 = require("../constants");
10const open_1 = require("./open");
11const REDIRECT_PORT = 8123;
12const REDIRECT_HOST = 'localhost';
13class OAuth2Flow {
14 constructor({ authorizationUrl, tokenUrl, clientId, redirectHost = REDIRECT_HOST, redirectPort = REDIRECT_PORT }, e) {
15 this.e = e;
16 this.authorizationUrl = authorizationUrl;
17 this.tokenUrl = tokenUrl;
18 this.clientId = clientId;
19 this.redirectHost = redirectHost;
20 this.redirectPort = redirectPort;
21 }
22 get redirectUrl() {
23 return `http://${this.redirectHost}:${this.redirectPort}`;
24 }
25 async run() {
26 const verifier = this.generateVerifier();
27 const challenge = this.generateChallenge(verifier);
28 const authorizationParams = this.generateAuthorizationParameters(challenge);
29 const authorizationUrl = `${this.authorizationUrl}?${qs.stringify(authorizationParams)}`;
30 await open_1.open(authorizationUrl);
31 const authorizationCode = await this.getAuthorizationCode();
32 const token = await this.getAccessToken(authorizationCode, verifier);
33 return token;
34 }
35 async getSuccessHtml() {
36 const p = path.resolve(constants_1.ASSETS_DIRECTORY, 'sso', 'success', 'index.html');
37 const contents = await utils_fs_1.readFile(p, { encoding: 'utf8' });
38 return contents;
39 }
40 async getAuthorizationCode() {
41 if (!(await utils_network_1.isPortAvailable(this.redirectPort))) {
42 throw new Error(`Cannot start local server. Port ${this.redirectPort} is in use.`);
43 }
44 const successHtml = await this.getSuccessHtml();
45 return new Promise((resolve, reject) => {
46 const server = http.createServer((req, res) => {
47 if (req.url) {
48 const params = qs.parse(req.url.substring(req.url.indexOf('?') + 1));
49 if (params.code) {
50 res.writeHead(200, { 'Content-Type': 'text/html' });
51 res.end(successHtml);
52 req.socket.destroy();
53 server.close();
54 resolve(Array.isArray(params.code) ? params.code[0] : params.code);
55 }
56 // TODO, timeout, error handling
57 }
58 });
59 server.listen(this.redirectPort, this.redirectHost);
60 });
61 }
62 async getAccessToken(authorizationCode, verifier) {
63 const params = this.generateTokenParameters(authorizationCode, verifier);
64 const { req } = await this.e.client.make('POST', this.tokenUrl);
65 const res = await req.send(params);
66 return res.body.access_token;
67 }
68 generateVerifier() {
69 return this.base64URLEncode(crypto.randomBytes(32));
70 }
71 generateChallenge(verifier) {
72 return this.base64URLEncode(crypto.createHash('sha256').update(verifier).digest());
73 }
74 base64URLEncode(buffer) {
75 return buffer.toString('base64')
76 .replace(/\+/g, '-')
77 .replace(/\//g, '_')
78 .replace(/=/g, '');
79 }
80}
81exports.OAuth2Flow = OAuth2Flow;
82const AUTHORIZATION_URL = 'https://auth.ionicframework.com/authorize';
83const TOKEN_URL = 'https://auth.ionicframework.com/oauth/token';
84const CLIENT_ID = '0kTF4wm74vppjImr11peCjQo2PIQDS3m';
85const API_AUDIENCE = 'https://api.ionicjs.com';
86class Auth0OAuth2Flow extends OAuth2Flow {
87 constructor({ email, connection, audience = API_AUDIENCE, authorizationUrl = AUTHORIZATION_URL, tokenUrl = TOKEN_URL, clientId = CLIENT_ID, ...options }, e) {
88 super({ authorizationUrl, tokenUrl, clientId, ...options }, e);
89 this.e = e;
90 this.email = email;
91 this.connection = connection;
92 this.audience = audience;
93 }
94 generateAuthorizationParameters(challenge) {
95 return {
96 audience: this.audience,
97 scope: 'openid profile email offline_access',
98 response_type: 'code',
99 connection: this.connection,
100 client_id: this.clientId,
101 code_challenge: challenge,
102 code_challenge_method: 'S256',
103 redirect_uri: this.redirectUrl,
104 };
105 }
106 generateTokenParameters(code, verifier) {
107 return {
108 grant_type: 'authorization_code',
109 client_id: this.clientId,
110 code_verifier: verifier,
111 code,
112 redirect_uri: this.redirectUrl,
113 };
114 }
115}
116exports.Auth0OAuth2Flow = Auth0OAuth2Flow;