The oidc-client is pretty large. That is, the code for oidc-client itself is small (around 15K) but the dist with all dependencies in minimal form is around 90K. Is it possible to reduce this size? E.g.,
I'm using oidc-client on a smart-phone webapp, where it takes significant time to load the library.
Yes, I'm sure. I'm in the middle of trying to find time to do some rework so perhaps after that rework we'll have a smaller library. Not sure yet tho.
Given the recent changes, I don't see this happening. The main issue is the jsrsasign library. It's that library that you would want to focus on. Maybe open an issue there?
Given the recent changes, I don't see this happening. The only other option is to factor our the jsrsasign code into a separate library, or contact that author to see what can be done to reduce his library in size.
I have app with these dependencies: classnames, lodash, react, react-dom, react-redux, react-router, react-router-redux, redux, seamless-immutable. Webpack total size for vendors is: _288 KB (294Â 912 bytes)_
I add oidc-client to my dependencies and total size for vendors is now: _616 KB (630Â 784 bytes)_
Total show stopper for me. I understand the reasoning that extra size comes from transitive dependency, but it's so bad that I would consider hard to not use it.
Well, it's all from the crypto library. Feel free to let them know they need to optimize it.
@brockallen I have a suggestion, maybe split this to multiple modules? Not a simple thing, but anyway.
I want to have implicit flow, I don't think I need any of crypto dependencies. I believe I only need "authorize" (generates the url which to redirect or flash in iframe to re-create bearer), "verify" that works as redirecturi parser, and "logout" url creator.
If you're accepting id_tokens, then you need the crypto. If you're not, then you're just doing OAuth2 and there are plenty of other JS libraries out there that only do OAuth2.
@brockallen I'm not well read on this. Not sure where I need id_token, except at logout which requires id_token_hint. The authroization already gives me access_token in url and API's seem to always accept it as bearer.
I don't think I need to decrypt the id_token on SPA js application. It's contents are trivial I can just query them from my API instead.
Does the JS need to know who the user is or any info about them? That's what the id_token conveys.
@brockallen yes, I got it. Official SPA js app does not need to know, because it can use API call with bearer. I understand this is required when connecting to 3rd party e.g. Google OpenId or some such, when there is no API call to ask with access_token who are you. Thanks for your help, will look for oauth2 libs!
Reopening to investigate this when I get some time: https://twitter.com/rmhrisk/status/775126946854211585
This issue on jsrassign can also help to reduce the size of this library when updating the dependency to 6.0.0.
Nice & good timing. I'll look into it. Thanks
jsrsasign 6.1.0 only brought us from 412K dist/min to ... uhh... 422K. that sucks.
BTW ~80K is webpack polyfill
depending on what is needed you can only load the necessary polyfills https://github.com/zloirock/core-js#commonjs
Is this still targeted @ 1.3.0? Love this js library. If the size can be more reasonable, it would be perfect. Regarding polyfills, as far as I understand, should it be more of a requirement/prerequisite for the consumer of the lib, instead of a hard dependency for the lib itself? I mean, what if I already have a different polyfill can do the work?
I don't know how much it'd actually help, but something like rollupjs w/ tree shaking might help.
If the size can be more reasonable, it would be perfect
Agreed. Any help is appreciated, since I'm working on this in my spare time.
Maybe this package will help reduce the size of the crypto dependencies. crypto-js allows modular imports which enables us to only import the things we need, unlike jsrsassign which is just one large blob.
Perhaps it can help... i don't see x509 anywhere tho...
If crypto-js doesn't have X509 support maybe this library can help :)
@brockallen i got id_token and access_token back from my identityServer 4 but also think this package is too large.
My question is same as @Ciantic, i can try do it all using pure OAuth without x509 crypto? Is that safe ?
I need other external provider too (google, etc)
If i just send the access_token to my api i can validate it there against my STS (IS4) right ?
Thanks
Recent work in jsrsasign: https://twitter.com/kjur/status/823178853661061122
Right now jsrasign is packaged with this library and adds to its size. Adding jsrasign to externals in webpack config would replace it by require('jsrasign'). Since jsrasign is a dependency of this library, npm will download it anyway and it will be available via require.
This would help to significantly reduce the size of the lib and dist files and shift the problem back to jsrasigns side.
See the wepback docs on externals for details.
This would help to significantly reduce the size of the lib and dist files and shift the problem back to jsrasigns side.
Yea, I'd not yet looked at the work/changes done on his side, so you might be right that the ultimate size issue remains the same.
It certainly won't solve the problem until jsrasign reduces its size. However, I still believe it is a good idea to use the externals so that a double-bundling & minification - once by jsrasign's creator & secondy when building this library - doesn't occur. It would also clean up the lib & dist files and remove unnecessary clutter from them.
https://github.com/kjur/jsrsasign/wiki/NOTE-jsrsasign-subset-package
From main page apparently 8.0.0 will remove unnecessary/outdated stuff. So will be smaller.
Forgive my naivety but why do you need to validate id_token at all? Under what circumstances can something go bad if you are sent a tampered with id_token?
Forgive my naivety but why do you need to validate id_token at all?
This is the whole point of this library and is what makes it OIDC compliant. It provides a signed protocol response so your client knows it's not being fooled and so your can trust the data you get back for the user. If you just want OAuth2 (which doesn't provide that guarantee), then there are lots of other libraries to choose from.
Ahhh right! Makes sense.
Btw.. you can save at least 10 bytes by removing the unnecessary check for '-' here https://github.com/IdentityModel/oidc-client-js/blob/dev/src/random.js#L28 ;)
Hey @brockallen,
I'd be happy to help out with some of the work on reducing the bundle size. I've got a few suggestions which I'll open a PR for shortly.
From what I can tell, the library is using only a few es6 features which require polyfilling. Initially, we can just load them in the webpack entryPoint, however core-js allows us to require functions that don't pollute the global namespace or modify existing objects. Often SPAs will be including polyfills in their own entrypoints, so adopting this approach would encapsulate and protect the library from other unintended polyfills leaking in.
ES6 Features the library is using (there may be others):
require('core-js/es6/promise');
require('core-js/fn/function/bind');
require('core-js/fn/object/assign');
require('core-js/fn/object/assign');
require('core-js/fn/array/find');
require('core-js/fn/array/some');
require('core-js/fn/array/is-array');
require('core-js/fn/array/splice');
Switching to these core-js polyfills can save 66.1kb on the bundle size.
The other source of possible reduction in file size is the logs. I've done some tests, and it appears that dropping the debug logs from the production build can save ~13kb on the minified bundle. One common pattern in the React ecosystem is to strip debug tools via Webpack's DefinePlugin when NODE_ENV === "production". I will include an implementation in the PR, in order not to make it a breaking change, we can introduce a third build target, perhaps bundle.prod.min.js.
Next thing I planned on looking at was a crypto lib that supports tree-shaking/dead code elimination. Would you prefer we introduce these initial optimisations in one PR, then look at crypto separately?
@JoshBarr -- sure, all sounds good. And yes, let's do these small ones first then the crypto after. To be honest, though, these small changes will be small compared to any savings we get with the crypto, so perhaps that's the bigger win?
It occurred to me that while a compliant library should – for completeness – work with all kinds of crypto implementations, the majority of implementers will likely be working with a subset of EC* or RSA* or PS*, rather than all nine algorithms.
Perhaps allowing users to generate their own builds with just the crypto implementations they require would help reduce the bundle size further? I think this can be achieved with Webpack, by introducing an interface around the crypto library.
For example:
// JoseUtil.js
import cryptoLib from './crypto/crypto-rsa'; // or crypto-es, crytpo-jsrsasign, etc...
const { jws, KeyUtil, X509, crypto, hextob64u, AllowedSigningAlgs } = cryptoLib;
// ...
// crypto-rsa.js
// .. slim implementations of required crypto features...
export default {
jws,
KeyUtil,
X509,
crypto,
hextob64u,
AllowedSigningAlgs
};
Then, build the module a custom webpack build:
// webpack.custom.rsa.js
plugins: [
// replace the bundled crypto implementation with the slim one we need.
new webpack.NormalModuleReplacementPlugin(/(.*)crypto-jsrassign(\.*)/, (resource) => {
resource.request = resource.request.replace(/crypto-jsrassign/, `crypto-rsa`);
}),
]
I realise this is quite abstract, I'll provide a working example of this.
I like that idea for advanced users that know how to do that and know what algs their STS supports. Most people won't be in that category, I fear.
One thing that adds size too is the dependency to babel-polyfill. The babel-polyfill lib is huge too and it seams that only some polyfills are required, but it's hard to say which ones. Can you provide some insights what is really required?
I had to include babel-polyfill only to get oidc-client working in Internet Explorer.
I think @JoshBarr started that research...
Has there been any further thought or work on this issue? Even gzipped this library ends up being ~40% of my entire bundle size.
Has anybody tried updating from 5.1.0 to 8.0.4, or is there a breaking change blocking this?
Edit:
Simply cloning the project and running the app, and everything _seems_ like it's working. There is a failed test, but only one:
JoseUtil validateJwt should validate from RSA X509 key:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
It appears there's an issue in the call to X509.getPublicKeyFromCertPEM on line 36 of JoseUtil.js with the key that is being provided.
Clearly not a fix, but a quick branch to save somebody some time if they have more working knowledge than I do: https://github.com/IdentityModel/oidc-client-js/pull/463/files
Thanks -- I'll have a look when I have time!
Just bumping this to see if @brockallen or anybody else has time
@brockallen
Whats with validating the id_token on server side middleware?
It is possible to have an extra endpoint in the api middleware to send the id_token, access_token, nonce ... etc.pp. and get back the user info? So we would not need this big crypto stuff on client side.
This is a total show stopper. This library is ~85Kb GZipped.!!!! Has anyone came up with a way to optimize this library or found an alternative library?
Agreed, the file size renders the library unusable for real world apps. Apologies for this depressing statement, identityserver is great, but not so for web apps.
Way to get around for me was to load the file when the user click on the
login button.
On Mon, 30 Apr 2018, 2:20 pm Elger Mensonides, notifications@github.com
wrote:
Agreed, the file size renders the library unusable for real world apps.
Apologies for this depressing statement, identityserver is great, but not
so for web apps.—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/IdentityModel/oidc-client-js/issues/23#issuecomment-385354627,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAZAjpB0fcbfMtJ9BidqyTtR6PnK_wzYks5ttt6CgaJpZM4Hoj1z
.
I spent a good amount of time trying to improve this. What I ended up having to do is manually build jsrsasign and (one-by-one) remove each of their js file and test to see if it was needed (by running our unit tests). I'm not thrilled about this approach, but the jsrsasign project is sort of a nightmare when it comes to trying to build it or use some of their smaller files.
Unfortunately I was only able to bring the size down about ~25-30%, but I guess that's better than nothing. If someone wants to have a look, it's up on the "js_size" branch.
I was pretty comfortable with these changes to reduce the size, I merged the work to dev and put out a pre-release: [email protected]. Please test to ensure it's working.
I'll close to track completion, but please let me know here if any feedback. Thanks
If you're accepting id_tokens, then you need the crypto. If you're not, then you're just doing OAuth2 and there are plenty of other JS libraries out there that only do OAuth2.
There are, but how many of them have the quality of this one, and support code flow + PKCE in the browser? To be honest, I'm struggling to find any. Any ideas?
I would be more than happy to see an oidc-client fork that just drops all the crypto dependencies for supporting id_token validation, but still supports everything else, including discovery, UserInfo endpoints etc.
Yea, maybe in 2.0.
Still hitting ~400k with latest release.
Most helpful comment
Still hitting ~400k with latest release.