-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use lb access token #421
Use lb access token #421
Conversation
Can one of the admins verify this patch? |
2 similar comments
Can one of the admins verify this patch? |
Can one of the admins verify this patch? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @Traksewt, thank you for the pull request. The changes looks mostly good at the first quick read. I am little bit worried that the tests are covering only units in isolation, I'd like to see a test doing real REST invocation to make sure all things fit together as expected.
I think this is the place where to add such test:
strong-remoting/test/rest.test.js
Lines 2379 to 2380 in 565aba1
describe('client', function() { | |
describe('call of constructor method', function() { |
lib/rest-adapter.js
Outdated
// check for the loopback options to pass along. | ||
// It may have the access token that can be used | ||
if (!auth && args.length) { | ||
var options = args[args.length - 1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assumes that args
do not contain the callback
as the last argument, can we rely on this? I don't remember how exactly remote invocation works.
lib/rest-adapter.js
Outdated
* @param remotes | ||
* @param args | ||
*/ | ||
RestAdapter.prototype.extractAuth = function(remotes, args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this method should be private - the name should start with underscore and jsdoc should include @private
annotation.
lib/rest-adapter.js
Outdated
var auth = remotes.auth; | ||
// check for the loopback options to pass along. | ||
// It may have the access token that can be used | ||
if (!auth && args.length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's simplify this method by using reverse logic please.
if (auth || !args.length) return auth;
// process options ...
@slnode ok to test |
Thanks @bajtos, I was having trouble testing the REST in that unit test. As the fix was the setting auth for one loopback server hitting another loopback server, should I be creating an extra express/loopback (so 2 in total) in this unit test? I couldn't tell of how I could test the rest adapter setting the access token using the single server. I also added a config to enable passing through the LB Access Token, otherwise, people may inadvertently send their loopback token to other 3rd party REST endpoints. |
lib/remote-objects.js
Outdated
var adapter = new Adapter(this, options); | ||
// send the set options for this remote object and | ||
// the dynamic options passed in to create the adapter | ||
var adapter = new Adapter(this, Object.assign({}, this.options, options)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not look right to me. Remoting options are different from transport/adapter-specific options. Why is this change needed? Can we revert it please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK Bajtos. Thanks for the heads up. I got a neater solution using the actual Rest properties that doesn't need config code changes. the 'options.rest' config goes directly to the rest adapter already.
lib/remote-objects.js
Outdated
@@ -132,7 +134,7 @@ RemoteObjects.prototype.connect = function(url, name) { | |||
} | |||
|
|||
var Adapter = this.adapter(name); | |||
var adapter = new Adapter(this); | |||
var adapter = new Adapter(this, this.options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I mentioned above, this.options
are usually different from adapter options. For example (and IIRC), the configuration of REST adapter is specified in rest
property of remoting options.
I think we should add options
argument to connect
, to make this consistent with handler
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK I don't need this at all anymore, not even for the connect. As the Adapter gets it off the rest config.
lib/rest-adapter.js
Outdated
* @param args | ||
* @private | ||
*/ | ||
RestAdapter.prototype._extractAuth = function(remotes, args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the second thought, this implementation is very loopback-specific. We are trying to keep strong-remoting decoupled from loopback itself - this package should provide extension hooks allowing loopback to inject loopback-specific behaviour.
In this particular case, the function parsing the accessToken from the options argument should live in LoopBack. It can be provided to RestAdapter for example via the options
object which contains other related configuration too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main difference for this one, is that it is executed per request. E.g. for access tokens it changes for each different user hitting the server, that is why it doesn't fit in the other options object that is used to initialise the adapter.
I'll think about it to see if I can set this through loopback code. One option is making it like a basic function to get the auth, that I can override in some sort of boot script that iterates over all datasources and sets the more complex extractAuth programmatically on the adapter. Apart from this boot script solution feeling a bit hacky, I was also hoping that this might have been useful to developers that want loopback servers to hit other loopback servers securely (e.g. microservices). I was hoping it would have worked out of the box (after setting the config flag). Open to ideas here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did your solution below of using the meta to find the options. All it is looking for is an accessToken in an options object. I made a generic way to get an arg by name on RestMethod.
lib/rest-adapter.js
Outdated
// check for the loopback options to pass along. | ||
// It may have the access token that can be used | ||
if (auth || !args.length) return auth; | ||
var options = args[args.length - 1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if it's a good idea to always assume the last argument is options
. Can we perhaps parse remoting metadata for the invoked method to verify that it has options
argument at the expected position?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, with a getArgByName in RestMethod.
test/http-invocation.test.js
Outdated
Authorization: 'abc' | ||
} | ||
}; | ||
expect(inv.createRequest()).to.eql(expectedReq); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assert is checking too much. If we change the underlying implementation in the future (e.g. by adding more fields to the returned request), then this test will fail despite the fact that the implementation may still be correct.
Please check only that request headers contain the expected authorization.
expect(inv.createRequest().headers).to.have.property('Authorization', 'abc');
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Np. I was copying all the following methods, but this change is more stable.
👍 |
I think a single server is enough. You can create the access token via javascript API by calling something like |
@bajtos please check |
@Traksewt thank you for the pull request, I'll take a look next week. I see that our CI builds are failing because one of our dependencies dropped support for Node.js 0.x, I think I'll need to fix our CI config before landing this patch, to get a green build first. |
Here is a pull request that should fix our CI in the 2.x branch: #428 |
@Traksewt sorry for realizing this only now: the changes you are proposing are effectively adding a new feature. Per our LTS rules, we are not adding any new features to the version lines that are in LTS or maintenance mode, and the version line 2.x is in LTS right now. Could you please rework your patch on top of the GitHub made it recently possible to change the target branch of a pull request: click in "edit" button on the right end of pull request title, and pick |
There were too many conflicts so made a new pull #430 |
Description
Allow the rest connector to call other loopback services by passing on the user authorization from the options where available. This is the fallback if no other authorization is specified.
This allows loopback servers to communicate securely with other loopback servers by passing on the auth token. Useful for using loopback as microservices.
Related issues
Checklist
guide