[next] Cookie Support (#2339)

* feat: added cookie support to coral

* feat: adapt client to use cookies

* fix: safari input styles

* fix: lint

* fix: linting

* fix: support clearing cookies properly, oauth

* feat: support cookies for websocket upgrade requests

* fix: lint

* fix: tests
This commit is contained in:
Wyatt Johnson
2019-06-25 21:48:58 +02:00
committed by Vinh
parent 3576b6a943
commit e72b15c505
79 changed files with 375 additions and 278 deletions
@@ -62,7 +62,7 @@ export interface CoralContext {
eventEmitter: EventEmitter2;
/** Clear session data. */
clearSession: () => Promise<void>;
clearSession: (nextAccessToken?: string | null) => Promise<void>;
/** Controls router transitions (for tests) */
transitionControl?: TransitionControlData;
@@ -8,7 +8,11 @@ import { Environment, RecordSource, Store } from "relay-runtime";
import uuid from "uuid/v1";
import { getBrowserInfo } from "coral-framework/lib/browserInfo";
import { LOCAL_ID } from "coral-framework/lib/relay";
import {
commitLocalUpdatePromisified,
LOCAL_ID,
setAccessTokenInLocalState,
} from "coral-framework/lib/relay";
import {
createLocalStorage,
createPromisifiedStorage,
@@ -105,7 +109,7 @@ function createRelayEnvironment(
const tokenGetter: TokenGetter = () => {
const localState = source.get(LOCAL_ID);
if (localState) {
return (localState.loggedIn && localState.accessToken) || "";
return localState.accessToken || "";
}
return "";
};
@@ -145,7 +149,7 @@ function createMangedCoralContextProvider(
}
// This is called every time a user session starts or ends.
private clearSession = async () => {
private clearSession = async (nextAccessToken?: string | null) => {
// Clear session storage.
this.state.context.sessionStorage.clear();
@@ -173,6 +177,13 @@ function createMangedCoralContextProvider(
// a new token.
subscriptionClient.setAccessToken(newTokenGetter());
// Set next access token.
if (nextAccessToken) {
await commitLocalUpdatePromisified(newEnvironment, async store => {
setAccessTokenInLocalState(nextAccessToken, store);
});
}
// Propagate new context.
this.setState(
{
@@ -292,7 +303,7 @@ export default async function createManaged({
uuidGenerator: uuid,
// Noop, this is later replaced by the
// managed CoralContextProvider.
clearSession: () => Promise.resolve(),
clearSession: (nextAccessToken?: string | null) => Promise.resolve(),
};
// Initialize local state.
@@ -25,14 +25,13 @@ export function setAccessTokenInLocalState(
const localRecord = source.get(LOCAL_ID)!;
localRecord.setValue(accessToken || "", "accessToken");
if (accessToken) {
const { payload, expired } = parseJWT(accessToken);
const { payload } = parseJWT(accessToken);
localRecord.setValue(payload.exp, "accessTokenExp");
localRecord.setValue(payload.jti, "accessTokenJTI");
localRecord.setValue(!expired, "loggedIn");
// TODO: (cvle) maybe a timer to detect when accessToken has expired?
} else {
localRecord.setValue(null, "accessTokenExp");
localRecord.setValue(null, "accessTokenJTI");
localRecord.setValue(false, "loggedIn");
}
}
@@ -41,10 +40,6 @@ export async function initLocalBaseState(
{ localStorage }: CoralContext,
accessToken?: string | null
) {
if (accessToken === undefined) {
accessToken = await localStorage!.getItem("accessToken");
}
commitLocalUpdate(environment, s => {
const root = s.getRoot();
@@ -52,7 +47,7 @@ export async function initLocalBaseState(
const localRecord = createAndRetain(environment, s, LOCAL_ID, LOCAL_TYPE);
root.setLinkedRecord(localRecord, "local");
// Set auth token
// Set access token
setAccessTokenInLocalState(accessToken || null, s);
});
}