Ultimate goal is to not require client app reload when log in is necessary.
I have from Authorizing in a popup or iframe
login() {
this.oidcSecurityService.authorize((authUrl) => {
// handle the authorrization URL
window.open(authUrl, '_blank', 'toolbar=0,location=0,menubar=0');
});
}
I am reaching but tried the following...
On the STS I created a SilentRenew View with the following script block.
@section script
{
<script>
window.onload = function () {
/* The parent window hosts the Angular application */
var parent = window.parent;
/* Send the id_token information to the oidc message handler */
var event = new CustomEvent('oidc-silent-renew-message', { detail: window.location.hash.substr(1) });
parent.dispatchEvent(event);
};
</script>
}
And my OpenIDImplicitFlowConfiguration is like this:
openIDImplicitFlowConfiguration.stsServer = 'http://localhost:5000';
openIDImplicitFlowConfiguration.redirect_url = 'http://localhost:4200';
openIDImplicitFlowConfiguration.client_id = 'angularOidcClient';
openIDImplicitFlowConfiguration.response_type = 'id_token token';
openIDImplicitFlowConfiguration.scope = 'webapi openid';
openIDImplicitFlowConfiguration.post_logout_redirect_uri = 'http://localhost:4200';
openIDImplicitFlowConfiguration.start_checksession = false;
openIDImplicitFlowConfiguration.silent_renew = true;
openIDImplicitFlowConfiguration.silent_renew_url = 'http://localhost:5000/Account/SilentRenew';
openIDImplicitFlowConfiguration.post_login_route = '/home';
// HTTP 403
openIDImplicitFlowConfiguration.forbidden_route = '/Forbidden';
// HTTP 401
openIDImplicitFlowConfiguration.unauthorized_route = '/home';
openIDImplicitFlowConfiguration.log_console_warning_active = true;
openIDImplicitFlowConfiguration.log_console_debug_active = true;
openIDImplicitFlowConfiguration.max_id_token_iat_offset_allowed_in_seconds = 10;
When the window opens, and after successful log in, its redirected to the "post_login_route" of /home.
I need to close that window and pass the window.location.hash(I presume?) back to the parent form and then automatically close the window. I assumed I do that with new CustomEvent.
Do I create a custom View for openIDImplicitFlowConfiguration.redirect_url or ??
Thanks for any help
Just curious - does it have to be a window? Could it be a modal dialog? Not sure that will help ...
Ultimately it will be a Material Dialog(iframe? presume) that all of our apps will consume. Was trying to build up to the knowledge without being too specific.
Currently when our site is on a phone and that tab is not visible, after an amount of time a user is no longer logged in. Need their state preserved and a dialog to indicate need to log back in.
I am also curious about how this is supposed to work.
@damienbod are there any examples of how to use the new authorize method with callback?
It certainly works in that I can have a popup that shows the auth window, but then it's not clear what to do after successful sign in in the popup window.
Do we need to push an event back to the parent? How do we have the parent pick up that the login was successful?
Hi @profet23
you need to replace the old tokens. This should be automatic is you use the authorize function
You can check if the tokens are updated in the browser dev tools.
Greetings Damien
@damienbod so are you saying:
1) call the authorize method with callback to open a pop up window to show auth url.
2) sign in via pop up
3) when sign in is completed via popup call authorize without callback in main window
?
I have gotten it to work by manually calling refreshsession in the main window after sign in, but it's not clear if this is the correct workflow.
@profet23 yes this should work. The workflow is correct, what you usually want is to update the tokens, without refresh the client application.
So the question is, how do you KNOW that the login is complete to refresh? I can get it to do the login process in the iframe of a dialog popup that I do, however I don't have any way to know that it completed and close it.
If you subscribe to the getIsAuthorized it calls in the separate iframe, not in the root window.
So I have no idea how to close the login window and cause the refresh of the parent's token.
Given the penalty in reloading a site after a login redirect because it has to reload the entire angular structure I think it would be a really good idea to have a sample on how to make this work because I can't imagine that this isn't the preferred method for anyone using this.
I'm also interested is it any bult-in mechanism to close window and update token after successfully autorization?
Any updates on this?
Is this necessary anymore? In the latest versions of the lib, if you enable silent_renew you'll no longer need to redirect/refresh the page to authenticate (provided the user is already authenticated with the authority).
What are you looking to accomplish?
@damienbod to me, everything that is trying to be accomplished here is now doable via getIsAuthorized(), silent renew, and check session.
Am I wrong? @sukhbirsaini if you have something specific that isn't doable. Let us know.
@profet23, my question was unrelated to silent renew. It was how
to not require client app reload when log in
The full extent of what we were trying to accomplish was..
Say user is logged into many client apps of ours, many tabs in browser. They log out of one client. We detect this and provide the opportunity to re-login, in all other apps, by providing credentials. In this specific case, we don't want to nav to our Auth site as we would like to preserve the particular apps state. As far as OIDC / idsrvr4 is concerned, this is a new login.
Another developer solved the issue by using a window.post to the parent window as I recall.
The full extent of what we were trying to accomplish was..
Say user is logged into many client apps of ours, many tabs in browser. They log out of one client. We detect this and provide the opportunity to re-login, in all other apps, by providing credentials. In this specific case, we don't want to nav to our Auth site as we would like to preserve the particular apps state. As far as OIDC / idsrvr4 is concerned, this is a new login.Another developer solved the issue by using a
window.postto the parent window as I recall.
@ttugates
Right.
So let's look at this:
ClientApp.1. When getIsAuthorized() is called it will return false as the user is not logged into the Authority.ClientApp.1 either opens a popup to the authority or redirects.ClientApp.1 either in the main browser window or in the popup. If in the popup, the popup posts a message back to the main tab with the hash received from the authority, and authentication continues as normal in the library.After that:
ClientApp.2. When getIsAuthorized() is called it will return true as the user is already logged into the Authority.ClientApp.1 and ClientApp.2 will utilize the check session routine to validate that the user is still logged in. That's what I meant bu silent renew and check session.
This is all present in the latest version of the library 7.0.2.
Previously getIsAuthorized() did not utilize the silent renew to check if the user was already logged in.
Basically the reason I'm looking for this is that angular apps take a while to load which is made worse while doing login because the login will normally be to something that isn't using Angular.
So I'm looking to eliminate the angular reload delay and have it all in an iframe that returns to a page that isn't angular and then the angular page picks up the navigation and loads in the login. (Basically a static page will receive the redirect and then then the angular will process it eliminating seconds from reload)
@JohnGalt1717 see my comment above
@profet23 how does one past it back to the parent window? I don't see anything in the documentation (at least the last time I looked)
@JohnGalt1717
The answer is... any way you want.
You can look at how silent renew handles it
They key is that you need to take the hash that you get from the popup (after the authority redirects back to the popup) and pass it back to the main window and call: authorizedCallback(theHash)
You can do this similar to this:
<script>
window.onload = function () {
/* The parent window hosts the Angular application */
var parent = window.opener;
/* Send the id_token information to the oidc message handler */
var event = new CustomEvent('oidc-popup-auth-message', {detail: window.location.hash.substr(1) });
parent.dispatchEvent(event);
};
</script>
You'll need to make sure you register for the oidc-popup-auth-message event in your angular app.
@profet23
Following your example and presuming the following is desired.
Present pop-up to user to relog in?
After popup success. How is that passed back to parent window? This presumes the popup is using an iFrame in and of itself.
@ttugates
sorry.. just edited my comment.. meant to put window.opener rather than window.parent
@profet23, thanks. I recall that as being roughly what we did. Will be a while before I get back to that code and verify.
@damienbod does this need better documentation?
@profet23 I don't think so, because this is not really a standard flow and the silent renew code is documented as well as this issue. But if you have an idea that would help, it's always good.
Greetings Damien
I think this can be closed then. As I believe everything has been addressed.
Hi @profet23 ,
Let me get you through the workflow I'm facing issue
MVC DotNet Core App Identity server code:
Add below code in the login page:
window.onload = function () {
debugger;
/* The parent window hosts the Angular application */
var parent = window.opener;
/* Send the id_token information to the oidc message handler */
var event = new CustomEvent('oidc-popup-auth-message', { detail: window.location.hash.substr(1) });
parent.dispatchEvent(event);
};
In Angular 6 app:
On login button:
this.oidcSecurityService.authorize((authUrl) => {
debugger;
this.attrHref = authUrl + '&from=iFrame';
this.isCollapsed = false;
});
Html of nav bar with login button contains dropdown with iframe as
<iframe #iframe width="420" height="345" [src]="attrHref | safe" frameborder="1">
</iframe>
Here is the error
Uncaught TypeError: Cannot read property 'dispatchEvent' of null
at window.onload (JavaScript.js:7)

With your login button... Are you actually opening a pop-up? I don't see a window.open call.
Oh I see.. you are using an iframe... Not a pop-up. Then you want window.parent. not window.opener.
The exact error now i'm facing is:
Uncaught DOMException: Blocked a frame with origin "http://localhost:5000" from accessing a cross-origin frame.
at window.onload (http://localhost:5000/js/JavaScript.js:7:12)
Are your redirect iframe url and angular app on different domains(origins)? They should be on the same domain.
To be clear. The window that contains the window .onload function should be hosted on the same domain as your angular app.
Ok.. I have fixed cross domain issue:
Now when listening to the same event as mentioned
`
window.addEventListener('oidc-popup-auth-message', this.handleMessage, false);
handleMessage(event): void {
this.oidcSecurityService.authorizedCallback();
}
`
i'm facing TypeError: Cannot read property 'authorizedCallback' of undefined
When handling listener callback in handle message, then the scope of this changed to window, and not pointing to the angular controller.
this.oidcSecurityService is not defined for whatever reason. You'll need to figure out why.
My guess is that you aren't binding corrently, and thus losing scope of this.
also, when you do figure out why, you'll need to pass the hash from the event to the authorizedCallback() call.
so like:
this.oidcSecurityService.authorizedCallback(e.detail);
Ok I have figured that out, using arrow function that binds automatically the 'this' to the function.
Thanks it is now working. I was able to complete the iframe authentication.
Awesome! Glad you're all sorted. I think maybe we're good to close this now... maybe? lol