@delewis13/appauth
Version:
A general purpose OAuth client. Vendored awaiting PR merge
198 lines (177 loc) • 7.02 kB
text/typescript
/*
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
// Represents the test web app that uses the AppAuthJS library.
import {AuthorizationRequest} from '../authorization_request';
import {AuthorizationNotifier, AuthorizationRequestHandler} from '../authorization_request_handler';
import {AuthorizationServiceConfiguration} from '../authorization_service_configuration';
import {log} from '../logger';
import {RedirectRequestHandler} from '../redirect_based_handler';
import {GRANT_TYPE_AUTHORIZATION_CODE, GRANT_TYPE_REFRESH_TOKEN, TokenRequest} from '../token_request';
import {BaseTokenRequestHandler, TokenRequestHandler} from '../token_request_handler';
import {TokenResponse} from '../token_response';
import { AuthorizationResponse } from '../authorization_response';
import { StringMap } from '../types';
/* Some interface declarations for Material design lite. */
/**
* Snackbar options.
*/
declare interface SnackBarOptions {
message: string;
timeout?: number;
}
/**
* Interface that defines the MDL Material Snack Bar API.
*/
declare interface MaterialSnackBar {
showSnackbar: (options: SnackBarOptions) => void;
}
/* an example open id connect provider */
const openIdConnectUrl = 'https://accounts.google.com';
/* example client configuration */
const clientId = '674027045299-a31g2q39v6qgngqvh8psi99km931rn8f.apps.googleusercontent.com';
const clientSecret = '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';
const redirectUri = 'http://localhost:8000/app/redirect.html';
const scope = 'openid profile email';
/**
* The Test application.
*/
export class App {
private notifier: AuthorizationNotifier;
private authorizationHandler: AuthorizationRequestHandler;
private tokenHandler: TokenRequestHandler;
// state
private configuration: AuthorizationServiceConfiguration|undefined;
private request: AuthorizationRequest|undefined;
private response: AuthorizationResponse|undefined;
private code: string|undefined;
private tokenResponse: TokenResponse|undefined;
constructor(public snackbar: Element) {
this.notifier = new AuthorizationNotifier();
this.authorizationHandler = new RedirectRequestHandler();
this.tokenHandler = new BaseTokenRequestHandler();
// set notifier to deliver responses
this.authorizationHandler.setAuthorizationNotifier(this.notifier);
// set a listener to listen for authorization responses
this.notifier.setAuthorizationListener((request, response, error) => {
log('Authorization request complete ', request, response, error);
if (response) {
this.request = request;
this.response = response;
this.code = response.code;
this.showMessage(`Authorization Code ${response.code}`);
}
});
}
showMessage(message: string) {
const snackbar = (this.snackbar as any)['MaterialSnackbar'] as MaterialSnackBar;
snackbar.showSnackbar({message: message});
}
fetchServiceConfiguration() {
AuthorizationServiceConfiguration.fetchFromIssuer(openIdConnectUrl)
.then(response => {
log('Fetched service configuration', response);
this.configuration = response;
this.showMessage('Completed fetching configuration');
})
.catch(error => {
log('Something bad happened', error);
this.showMessage(`Something bad happened ${error}`)
});
}
makeAuthorizationRequest() {
// create a request
let request = new AuthorizationRequest({
client_id: clientId,
redirect_uri: redirectUri,
scope: scope,
response_type: AuthorizationRequest.RESPONSE_TYPE_CODE,
state: undefined,
extras: {'prompt': 'consent', 'access_type': 'offline'}
});
if (this.configuration) {
this.authorizationHandler.performAuthorizationRequest(this.configuration, request);
} else {
this.showMessage(
'Fetch Authorization Service configuration, before you make the authorization request.');
}
}
makeTokenRequest() {
if (!this.configuration) {
this.showMessage('Please fetch service configuration.');
return;
}
let request: TokenRequest|null = null;
if (this.code) {
let extras: StringMap|undefined = undefined;
if (this.request && this.request.internal) {
extras = {};
extras['code_verifier'] = this.request.internal['code_verifier'];
}
// use the code to make the token request.
request = new TokenRequest({
client_id: clientId,
client_secret: clientSecret,
redirect_uri: redirectUri,
grant_type: GRANT_TYPE_AUTHORIZATION_CODE,
code: this.code,
refresh_token: undefined,
extras: extras
});
} else if (this.tokenResponse) {
// use the token response to make a request for an access token
request = new TokenRequest({
client_id: clientId,
client_secret: clientSecret,
redirect_uri: redirectUri,
grant_type: GRANT_TYPE_REFRESH_TOKEN,
code: undefined,
refresh_token: this.tokenResponse.refreshToken,
extras: undefined
});
}
if (request) {
this.tokenHandler.performTokenRequest(this.configuration, request)
.then(response => {
let isFirstRequest = false;
if (this.tokenResponse) {
// copy over new fields
this.tokenResponse.accessToken = response.accessToken;
this.tokenResponse.issuedAt = response.issuedAt;
this.tokenResponse.expiresIn = response.expiresIn;
this.tokenResponse.tokenType = response.tokenType;
this.tokenResponse.scope = response.scope;
} else {
isFirstRequest = true;
this.tokenResponse = response;
}
// unset code, so we can do refresh token exchanges subsequently
this.code = undefined;
if (isFirstRequest) {
this.showMessage(`Obtained a refresh token ${response.refreshToken}`);
} else {
this.showMessage(`Obtained an access token ${response.accessToken}.`);
}
})
.catch(error => {
log('Something bad happened', error);
this.showMessage(`Something bad happened ${error}`)
});
}
}
checkForAuthorizationResponse() {
this.authorizationHandler.completeAuthorizationRequestIfPossible();
}
}
// export App
(window as any)['App'] = App;