Oidc-client-js: How to use this library in an Angular 2 spa

Created on 17 Jun 2016  路  31Comments  路  Source: IdentityModel/oidc-client-js

I'm wondering if there are any examples or guidance available on how to use this library in an angular 2 app?

I'm not hugely experienced in javascript development but I've had a go at using oidc-client in a simple app. However as soon as I add a reference (to the compiled version) in my index.html, the angular system seems to stop working. Triggering a click event starts it up again and data is rendered to the view as normal . Sign-in, get user, sign-out etc all seem to work well. However the ui does not get updated (unless I trigger a click afterward).

Is there something I'm missing that will get this playing nicely with Angular 2?

enhancement question

Most helpful comment

@brockallen
here's a quick example project of using this lib with angular 2. I threw it together relative quick and did a fast write up of how to get it working.
https://github.com/jmurphzyo/Angular2OidcClient

All 31 comments

I don't know Angular2, but I suspect they use a module system. This means you should be loading oidc-client from the "lib" folder (not the "dist" folder).

Ah now it's working better, thank you. If I import the library like this:

import * as Oidc from 'oidc-client/lib/oidc-client.js';

it seems to be working good at runtime. I'm using typescript and the compiler is not happy but I guess I just need a definitions file or something.

Yes, I have an open issue for TS file. Feel free to contribute one if you get the time.

does this seem right for the tsd? oidc-client.d.ts.... I haven't tested it yet. if someone has the time let me know.

@jmurphzyo i'll take a look when i can. also... i don't know TS... so i'll just assume all the syntax is legit.

@brockallen The only part that might be off is the JoseUtil because of the outside dependency. I made a custom .d.ts file I will post it as well. jsrsasign.d.ts it is missing several modules but those were the ones I saw odic depended on

I think the only things we really need to document are the public APIs, right?

yes, I actually just rewrote the library in typescript and those were all the definition files..

Also using this for Angular 2.

@jmurphzyo are you going to share the typescript version?

@brockallen if either @jmurphzyo did a pull request, or I rewrote this in typescript and did a pull request would you be happy to move to typescript?

I could set it up as a UMD module so it will still work as a vanilla lib if you are interested.

I'm really struggling with exactly how to get the UserManager working with an Angular2 spa. I want to automatically redirect to the login page when my spa page loads, but I seem to be having issues with how that flow should work. Can you guys please provide an example for this scenario?

Call getUser() at startup and if the returned value is null or the access token is expired, then call signinRedirect(). Does that not work for you?

@brockallen Thanks for the quick response. That's what I'm doing in my init:
let userPromise = this._userManager.getUser().then(function (user) { if (!user) { console.log("No user returned. Calling SigninRedirect!"); self._userManager.signinRedirect({ data: 'some data' }).then(function () { console.log("signinRedirect done"); }).catch(function (err) { console.log(err); }); } });

And this seems to get stuck in an infinite loop.

You should use a dedicated callback page for handling the response from the token service -- this way the sensitive handoff has fewer points of attack. Once it's done processing the callback then redirect back to your main app URL.

I'll give that a shot. Thanks again for the quick response and the guidance. I love the work you guys have done with IdentityServer and this library. Making my job much easier!!

I love the work you guys have done with IdentityServer and this library. Making my job much easier!!

Thanks. Feel free to encourage your company to hire us for an architecture review, code review, or something else like that :)

@brockallen The separate callback page did the trick. Thanks again! I'll see what I can do to get you guys in sometime :)

@tstone84 having some troubles of our own. This might help you or anyone else using a # in their URL.

As you can see below our SPA already has a # in the URL

redirect_uri: 'http://localhost:3000/#/main/login?', // this address and tenant

SigninResponse.js calls parse URL with a hard coded #

var values = UrlUtility.parseUrlFragment(url, "#");

We were getting an error that the id_token was not found as the response was being parsed from /main/etc.... Our parameters were being returned all as query parameters after the ?

To solve this we did a string replace

userManager.signinRedirectCallback(href.replace('#', '').replace('?', '#'))
     .then((result) => {
           console.log('result', result)
     })

@brockallen would be nice to have an optional param

var splitFrom = '#' || param.splitFrom;
var values = UrlUtility.parseUrlFragment(url, splitFrom);

Not sure the best place to set this option?

@vespertilian Sorry -- I didn't read your entire message. I see you're already passing the part of the URL to the API.

The reason I don't have anything else is that I didn't want to anticipate all the different frameworks how params might be passed and I wanted to avoid overloading the config system.

@brockallen Makes sense. Thank you for your work on this and your quick response.

Our current solution feels a little inelegant.
In angular we can also pull these param's off the URL. Do you think passing them in directly would be better? Does the library support this? Happy to help out if you like.

Also think about my offer to Typescriptify the project for you. Will still work as a vanilla JS library. One cool benefit of Typescript is you can use TypeDoc.

We have been using http://typedoc.io/ to document some of our internal modules in Typescript. You get lots of docs for free.

In angular we can also pull these param's off the URL.

Well, again, any given app can form that URL in any way. The only thing you need to do is pass the non-app part to the API.

@vespertilian did you see the pr this guy issued? #63

I have everything working well at this point, except for renewing access tokens. I have an Angular2 SPA and I'm capturing the AccessTokenExpiring event and allowing the user to decide to continue working or logout. The logout was easy. However, i'm struggling with which userManager method to call to refresh my data access token. It seems if I use signInSilent(), I will need to provide a silent redirect uri, which I assume the Idsvr will redirect to, which I'd rather not have, as it would redirect from where the user is currently working. Is there a solid example of what I should be doing??

Thanks!!

@brockallen If you want I will create a sample angular 2 project for you to put in the samples but the documentation would be fairly poor because I am limited on time but it's the least I can contribute!

@jmurphzyo sure, that'd be great. and we're all short on time :)

@brockallen
here's a quick example project of using this lib with angular 2. I threw it together relative quick and did a fast write up of how to get it working.
https://github.com/jmurphzyo/Angular2OidcClient

@jmurphzyo thanks. i added it as a link to the wiki for samples.

tstone84, I am entering an infinite loop as well. Can you share how you called this callback.html/ callback.component.ts page? A few lines of code on how this is being done?
This clientside code has me a bit confused. .NET was easier. Thanks

@DoubleExposure We ended up using a separate static callback.html page as Brock recommended. It's just a blank .html page with a script. Obviously, you will want to redirect or add additional logic to redirect where you would like the user to be redirected to. Here's the code in that page:
<script> new Oidc.UserManager().signinRedirectCallback().then(function(user) { console.log("signin response success", user); window.location.href = 'index.html'; }).catch(function(err) { console.log(err); }); </script>

@tstone84 I have trying static callback.html on new angular 4.0.0 but i can't, have you try it?

@kodelapan Yes, we are using a callback.html with Angular 4. The js in the html page looks something like this:
<script> new Oidc.UserManager().signinRedirectCallback().then(function(user) { console.log("signin response success", user); window.location.href = 'index.html'; }).catch(function(err) { console.log(err); }); </script>

Thanks, successfully after update angular to 4.0.2 and node 6

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dotli picture dotli  路  3Comments

m-andrew-albright picture m-andrew-albright  路  5Comments

iXmonvi33 picture iXmonvi33  路  4Comments

shesellsanctuary picture shesellsanctuary  路  4Comments

eckersalld picture eckersalld  路  5Comments