Skip to content

Commit

Permalink
Merge pull request #39 from immers-space/non-popup-token-retrieval
Browse files Browse the repository at this point in the history
Non popup token retrieval
  • Loading branch information
wmurphyrd authored Feb 8, 2024
2 parents 890d620 + 56cfc23 commit ab46f90
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 16 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## Unreleased

### Changed

* `catchToken` will now return the token and associated data if it does not detect an opener window to pass the data to
* `ImmersClient.loginWithToken` now also accepts sessionInfo parameter to be fully equivalent with regular login

## v2.16.0 (2023-03-29)

### Added
Expand Down
2 changes: 1 addition & 1 deletion oneLiner.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ try {
console.warn(`Unable to process query arguments to script, ${err.message}`)
}
(async function () {
if (catchToken()) {
if (catchToken() === true) {
// token was passed to opener window; this is just a popup
return
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"test": "standard",
"doc": "jsdoc -c jsdoc.config.json -d doc -r source/. -R README.md && cp -R readme_files doc/",
"build": "webpack --config webpack.prod.js",
"type": "tsc index.js source/**/*.js -t es2020 --declaration --skipLibCheck --allowJs --emitDeclarationOnly --moduleResolution node --outDir types",
"type": "tsc index.js -t es2020 --declaration --skipLibCheck --allowJs --emitDeclarationOnly --moduleResolution node --outDir types",
"dev": "webpack serve --open --config webpack.dev.js",
"prepare": "npm run type && npm run build"
},
Expand Down
41 changes: 30 additions & 11 deletions source/authUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,21 @@ export const allScopes = [
*/
export const roles = ['public', 'friends', 'modAdditive', 'modFull']

/**
* @typedef {object} TokenResult
* @property {string} token OAuth access token
* @property {string} homeImmer User's home Immers Server origin
* @property {Array<string>} authorizedScopes Scopes granted by user (may differ from requested scopes)
* @property {object} sessionInfo Any other params returned from the authorization server with the token
*/
/**
* Retrieve OAuth access token and authorization details from URL after
* redirect and pass it back to the opening window if in a pop-up
* redirect and pass it back to the opening window if in a pop-up. Returns true
* if a token was found and passed from popup to opener. Returns the token response
* data if a token was found but the window is not a popup
* (e.g. to pass on to [ImmersClient.loginWithToken]{@link ImmersClient#loginWithToken}).
* Returns false if no token found.
* @returns {boolean | TokenResult}
*/
export function catchToken () {
const hashParams = new URLSearchParams(window.location.hash.substring(1))
Expand All @@ -58,16 +70,23 @@ export function catchToken () {
const sessionInfo = Object.fromEntries(hashParams)
window.location.hash = ''
// If this is an oauth popup, pass the results back up and close
// todo check origin
if (window.opener) {
window.opener.postMessage({
type: 'ImmersAuth',
token,
homeImmer,
authorizedScopes,
sessionInfo
})
return true
try {
if (window.opener?.location.origin === window.location.origin) {
window.opener.postMessage({
type: 'ImmersAuth',
token,
homeImmer,
authorizedScopes,
sessionInfo
})
return true
}
} catch {}
return {
token,
homeImmer,
authorizedScopes,
sessionInfo
}
} else if (hashParams.has('error')) {
window.opener?.postMessage({ type: 'ImmersAuth', error: hashParams.get('error') })
Expand Down
8 changes: 5 additions & 3 deletions source/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,16 +189,18 @@ export class ImmersClient extends window.EventTarget {

/**
* Initialize client with an existing credential,
* e.g. one obtained through a service account
* e.g. one obtained through a service account or one returned from {@link catchToken}
* when performing a redirect based OAuth flow
* @param {string} token - OAuth2 Access Token
* @param {string} homeImmer - Domain (host) for user's home immer
* @param {(string|string[])} authorizedScopes - Scopes authorized for the token
* @param {object} [sessionInfo] - optional session data provided alongside token
* @returns {Promise<boolean>} true if the login was successful
*/
loginWithToken (token, homeImmer, authorizedScopes) {
loginWithToken (token, homeImmer, authorizedScopes, sessionInfo) {
homeImmer = getURLPart(homeImmer, 'origin')
authorizedScopes = preprocessScopes(authorizedScopes)
this.#store.credential = { token, homeImmer, authorizedScopes }
this.#store.credential = { token, homeImmer, authorizedScopes, sessionInfo }
return this.restoreSession()
}

Expand Down

0 comments on commit ab46f90

Please sign in to comment.