Skip to content

Commit

Permalink
Check token expiration before it gets used (#1067)
Browse files Browse the repository at this point in the history
  • Loading branch information
kraenhansen authored Jan 3, 2019
1 parent cc5cbc4 commit 1c8b62a
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 8 deletions.
1 change: 1 addition & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Fixed text rendering issue resulting in clipping of property name and types in the header of the browser window. It was only observed on Windows with high pixel density displays. ([#1059](https://github.com/realm/realm-studio/pull/1059), since v1.0.0)
- Fixed an issue where sidebars got resized when a window got resized despite the sidebar being collapsed. ([#1060](https://github.com/realm/realm-studio/pull/1060), since v2.7.0)
- Fixed potential issues from writing to partial Realms by opening them in a read-only mode. ([#1062](https://github.com/realm/realm-studio/pull/1062) & [#1063](https://github.com/realm/realm-studio/pull/1063), since v1.0.0)
- Fixed the error shown when connecting to a Realm Cloud instance with an expired token. ([#1067](https://github.com/realm/realm-studio/pull/1067), since v1.18.1)

## Internals
- Fixed the Dockerfile used when testing PRs. ([#1057](https://github.com/realm/realm-studio/pull/1057))
Expand Down
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
"fs-extra": "^4.0.2",
"isomorphic-fetch": "^2.2.1",
"json5": "^1.0.1",
"jwt-decode": "^2.2.0",
"keytar": "^4.3.0",
"memoize-one": "^3.1.1",
"mixpanel-browser": "^2.13.0",
Expand Down Expand Up @@ -171,6 +172,7 @@
"@types/isomorphic-fetch": "0.0.34",
"@types/jsdom": "^11.0.2",
"@types/json5": "0.0.29",
"@types/jwt-decode": "^2.2.1",
"@types/keytar": "^4.0.1",
"@types/mixpanel": "^2.13.0",
"@types/mocha": "^2.2.43",
Expand Down
4 changes: 2 additions & 2 deletions src/main/CloudManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ export class CloudManager {
public async refresh(justAuthenticated = false) {
const endpoint = raas.getEndpoint();
try {
const raasToken = raas.user.getToken();
if (raasToken) {
if (raas.user.hasToken()) {
const raasToken = raas.user.getToken();
this.sendCloudStatus({
kind: 'fetching',
endpoint,
Expand Down
40 changes: 34 additions & 6 deletions src/services/raas/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
//
////////////////////////////////////////////////////////////////////////////

import * as jwt from 'jwt-decode';
import * as moment from 'moment';

import {
buildUrl,
fetchAuthenticated,
Expand Down Expand Up @@ -79,6 +82,14 @@ export interface ISubscription {
projectDescription?: string | null;
}

interface ICloudJWT {
admin: boolean;
exp: number;
iat: number;
sub: string;
userId: string;
}

export const authenticateWithGitHub = async (
githubCode: string,
): Promise<IAuthResponse> => {
Expand Down Expand Up @@ -129,8 +140,27 @@ export const hasToken = () => {
return store.has(TOKEN_STORAGE_KEY);
};

/**
* Gets the token, throwing if it's expired
*/
export const getToken = (): string => {
return store.get(TOKEN_STORAGE_KEY);
const token = store.get(TOKEN_STORAGE_KEY);
if (token) {
const parsedToken = jwt<ICloudJWT>(token);
if (!parsedToken.exp) {
throw new Error('Expected an expiration in the JWT');
}
const expiration = moment.unix(parsedToken.exp);
if (expiration.isBefore(/* now */)) {
// The token has expired, forget about it and throw an error
forgetToken();
throw new Error('The token has expired');
} else {
return token;
}
} else {
throw new Error('Not authenticated');
}
};

export const setToken = (token: string) => {
Expand All @@ -143,12 +173,10 @@ export const forgetToken = () => {

export const getTenantCredentials = (url: string): IServerCredentials => {
return {
kind: 'other',
kind: 'jwt',
url,
options: {
provider: 'jwt/central-owner',
data: getToken(),
},
providerName: 'jwt/central-owner',
token: getToken(),
};
};

Expand Down
2 changes: 2 additions & 0 deletions src/ui/Greeting/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ class GreetingContainer extends React.Component<
}
} catch (err) {
showError('Failed to connect to the server', err);
// The cloud token might have been invalidated, refreshing the status will show this to the user.
await main.refreshCloudStatus();
}
};

Expand Down

0 comments on commit 1c8b62a

Please sign in to comment.