implemented oauth state parameter
This commit is contained in:
parent
135f40f65d
commit
d34ff79fd7
|
@ -80,7 +80,7 @@ module.exports = function() {
|
||||||
app.route('/signin', body(require('../pages/signin')));
|
app.route('/signin', body(require('../pages/signin')));
|
||||||
app.route('/api/fxa/oauth', async function(state, emit) {
|
app.route('/api/fxa/oauth', async function(state, emit) {
|
||||||
try {
|
try {
|
||||||
await state.user.finishLogin(state.query.code);
|
await state.user.finishLogin(state.query.code, state.query.state);
|
||||||
emit('replaceState', '/');
|
emit('replaceState', '/');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit('replaceState', '/error');
|
emit('replaceState', '/error');
|
||||||
|
|
14
app/user.js
14
app/user.js
|
@ -2,9 +2,10 @@
|
||||||
import assets from '../common/assets';
|
import assets from '../common/assets';
|
||||||
import { getFileList, setFileList } from './api';
|
import { getFileList, setFileList } from './api';
|
||||||
import { encryptStream, decryptStream } from './ece';
|
import { encryptStream, decryptStream } from './ece';
|
||||||
import { b64ToArray, streamToArrayBuffer } from './utils';
|
import { arrayToB64, b64ToArray, streamToArrayBuffer } from './utils';
|
||||||
import { blobStream } from './streams';
|
import { blobStream } from './streams';
|
||||||
import { getFileListKey, prepareScopedBundleKey, preparePkce } from './fxa';
|
import { getFileListKey, prepareScopedBundleKey, preparePkce } from './fxa';
|
||||||
|
import storage from './storage';
|
||||||
|
|
||||||
const textEncoder = new TextEncoder();
|
const textEncoder = new TextEncoder();
|
||||||
const textDecoder = new TextDecoder();
|
const textDecoder = new TextDecoder();
|
||||||
|
@ -54,6 +55,8 @@ export default class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
async login() {
|
async login() {
|
||||||
|
const state = arrayToB64(crypto.getRandomValues(new Uint8Array(16)));
|
||||||
|
storage.set('oauthState', state);
|
||||||
const keys_jwk = await prepareScopedBundleKey(this.storage);
|
const keys_jwk = await prepareScopedBundleKey(this.storage);
|
||||||
const code_challenge = await preparePkce(this.storage);
|
const code_challenge = await preparePkce(this.storage);
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
|
@ -62,7 +65,7 @@ export default class User {
|
||||||
code_challenge_method: 'S256',
|
code_challenge_method: 'S256',
|
||||||
response_type: 'code',
|
response_type: 'code',
|
||||||
scope: 'profile https://identity.mozilla.com/apps/send', //TODO param
|
scope: 'profile https://identity.mozilla.com/apps/send', //TODO param
|
||||||
state: 'todo',
|
state,
|
||||||
keys_jwk
|
keys_jwk
|
||||||
});
|
});
|
||||||
location.assign(
|
location.assign(
|
||||||
|
@ -70,7 +73,12 @@ export default class User {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async finishLogin(code) {
|
async finishLogin(code, state) {
|
||||||
|
const localState = storage.get('oauthState');
|
||||||
|
storage.remove('oauthState');
|
||||||
|
if (state !== localState) {
|
||||||
|
throw new Error('state mismatch');
|
||||||
|
}
|
||||||
const tokenResponse = await fetch(AUTH_CONFIG.token_endpoint, {
|
const tokenResponse = await fetch(AUTH_CONFIG.token_endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
Loading…
Reference in New Issue