Issue: In my angular app, when user clicks on logout button, following code gets called:
<button *ngIf="isLoggedin()" (click)="authService.logout()">Logout</button>
Implementation of AuthService.logout
logout(): Promise<any> {
return this._userManager.signoutRedirect();
}
AuthService constructor:
constructor(private httpClient: HttpClient, private router: Router) {
var config = {
authority: Constants.stsAuthority,
client_id: Constants.clientId,
redirect_uri: '${Constants.clientRoot}assets/oidc-login-redirect.html',
scope: 'openid profile',
response_type: 'id_token token',
post_logout_redirect_uri: '${Constants.clientRoot}?postLogout=true',
userStore: new WebStorageStateStore({ store: window.localStorage }),
};
this._userManager = new UserManager(config);
this._userManager.getUser().then(user => {
if (user && !user.expired) {
this._user = user;
}
});
}
Above call is throwing the following exception:
OidcClient.createSignoutRequest: No end session endpoint url returned
Upon some research, it seems like When userManager.signoutRedirect is called, it is internally calling methods which endup in the below call in oidc-client.js:
However, end_session_endpoint is not in the metadata of some of popular oauth providers and this method throws exception. Think this parameter should be made optional.
OidcClient.prototype.createSignoutRequest = function createSignoutRequest() {
var _this3 = this;
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
id_token_hint = _ref2.id_token_hint,
data = _ref2.data,
state = _ref2.state,
post_logout_redirect_uri = _ref2.post_logout_redirect_uri;
var stateStore = arguments[1];
_Log.Log.debug("OidcClient.createSignoutRequest");
post_logout_redirect_uri = post_logout_redirect_uri || this._settings.post_logout_redirect_uri;
return this._metadataService.getEndSessionEndpoint().then(function (url) {
if (!url) {
_Log.Log.error("OidcClient.createSignoutRequest: No end session endpoint url returned");
throw new Error("no end session endpoint");
}
_Log.Log.debug("OidcClient.createSignoutRequest: Received end session endpoint", url);
var request = new _SignoutRequest.SignoutRequest({
url: url,
id_token_hint: id_token_hint,
post_logout_redirect_uri: post_logout_redirect_uri,
data: data || state
});
var signoutState = request.state;
if (signoutState) {
_Log.Log.debug("OidcClient.createSignoutRequest: Signout request has state to persist");
stateStore = stateStore || _this3._stateStore;
stateStore.set(signoutState.id, signoutState.toStorageString());
}
return request;
});
};
Here is more discussion on this for google: Similar Github Issue at https://github.com/openid/AppAuth-iOS/issues/47
There should be an option to just clear local storage and let user stay signed in for the provider unless the provider supports signing out just for this client.
OidcClient.createSignoutRequest: No end session endpoint url returned
Sounds like your token server doesn't support signout.
You can work around this issue by manually adding the end_session_endpoint metadata property in addition to the required settings
const userManager = new UserManager({
// ...,
post_logout_redirect_url: 'http://localhost:3000/login',
metadata: {
// ...,
end_session_endpoint: 'http://localhost:3000/logout/callback', // Or however you want to clear sessionStorage or revoke the token
},
});
Most helpful comment
You can work around this issue by manually adding the
end_session_endpointmetadata property in addition to the required settings