-
Notifications
You must be signed in to change notification settings - Fork 56
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
First proposal for auth.setOptions() #260
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,23 +40,31 @@ var Auth = (function() { | |
|
||
function Auth(client, options) { | ||
this.client = client; | ||
this.tokenParams = options.defaultTokenParams || {}; | ||
this._setOptions(options); | ||
} | ||
|
||
Auth.prototype._setOptions = function(options) { | ||
this.tokenParams = this.tokenParams || options.defaultTokenParams || {}; | ||
|
||
/* RSA7a4: if options.clientId is provided and is not | ||
* null, it overrides defaultTokenParams.clientId */ | ||
if(options.clientId) { | ||
this.tokenParams.clientId = options.clientId; | ||
this.clientId = options.clientId | ||
var err = this.setClientId(options.clientId); | ||
if(err) { throw err; } | ||
} | ||
|
||
/* decide default auth method */ | ||
var key = options.key; | ||
if(key) { | ||
if(!options.clientId && !options.useTokenAuth) { | ||
if(!this.clientId && !options.useTokenAuth) { | ||
/* we have the key and do not need to authenticate the client, | ||
* so default to using basic auth */ | ||
Logger.logAction(Logger.LOG_MINOR, 'Auth()', 'anonymous, using basic auth'); | ||
if(this.method && this.method !== 'basic') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For clarity, should we not be writing these conditionals as |
||
throw new Error('Unable to update auth options with incompatible auth method'); | ||
} | ||
this.method = 'basic'; | ||
if(this.key && this.key !== key) { | ||
throw new Error('Unable to update auth options with incompatible key'); | ||
} | ||
this.key = key; | ||
this.basicKey = toBase64(key); | ||
return; | ||
|
@@ -77,6 +85,9 @@ var Auth = (function() { | |
throw new Error(msg); | ||
} | ||
/* using token auth, but decide the method */ | ||
if(this.method && this.method !== 'token') { | ||
throw new Error('Unable to update auth options with incompatible auth method'); | ||
} | ||
this.method = 'token'; | ||
if(options.token) { | ||
/* options.token may contain a token string or, for convenience, a TokenDetails */ | ||
|
@@ -97,7 +108,33 @@ var Auth = (function() { | |
Logger.logAction(Logger.LOG_ERROR, 'Auth()', msg); | ||
throw new Error(msg); | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Update the authentication options for this client; | ||
* this will also update these options on the realtime connection | ||
* so that they take effect immediately | ||
* @param options | ||
*/ | ||
Auth.prototype.setOptions = function(options) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dislike this API because I do not feel it is clear what it does and it creates ambiguity in regards to what I therefore propose we instead simply change the specification stating that calling The major issue I foresee with either approach at this stage is that if a user attempts to reauthorise and the new token details are incompatible with the old, then instead of simply rejecting the upgrade attempt, the connection will effectively move to the Also, @paddybyers can you confirm what happens if the user is assigned less privileges than before, will that be rejected or will the new privileges be applied and if any channels are attached that are not supported, they will be detached. I assume there are cases where privileges may be downgraded and I think we should support probably this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If you wanted to set a new token with new capabilities, how would
I'm not sure that the outcome would be much different in that case ...
The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In a number of ways:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Not according to the spec. See RSA10b and RSA10g.
Why not just call
Why not do it in authorise,
What's the problem. Calling
Yes you can |
||
this._setOptions(options); | ||
if(this.client instanceof Realtime) { | ||
this.client.connection.connectionManager.onAuthUpdated(); | ||
} | ||
}; | ||
|
||
Auth.prototype.setClientId = function(clientId) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The naming of this method implies it's a public method but should not be. Can we change it to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure |
||
if(clientId !== '*') { | ||
if(this.clientId && this.clientId !== clientId) { | ||
var msg = 'Unable to set incompatible clientId'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why shouldn't we let people change their clientId with a reauth? Edit: Matt points out that from realtime might not like you resuming a connection with a different clientId, which is fair enough. never mind There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Because it is currently a fixed attribute of a connection - you also can't resume or recover with a different There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can a user ever upgrade from no There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree we could consider that, but right now it is not supported. We shouldn't do it as part of this change IMO but address it when we do mutable auth where we can properly address the various upgrades that are possible. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Ok, but is the client library going to actively prevent this, or will it allow it if our upgrade later allowed it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Realtime actively prevents it currently. The library allows it, so you would get a failed connection instead of an exception which means the connection isn't touched. Given this is a temporary situation I'm not sure it really makes a big difference. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
What do yo mean the connection isn't touched?
I agree, but assuming we allow anonymous -> identified clients in realtime in the near future, it would be nice to know it will just work without any further changes here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The transport is not disconnected, and no new transport is created. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But you said the library allows it. So as far as I can tell, the following will happen.
So not sure why you say it's not touched. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
BTW. Something to consider, if we did support changing the |
||
return new ErrorInfo(msg, 40102, 401); | ||
} | ||
/* RSA7a4: if options.clientId is provided and is not | ||
* null, it overrides defaultTokenParams.clientId */ | ||
this.clientId = this.tokenParams.clientId = clientId; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If someone tries to call this with clientId of '*', we should probably throw an error (as we do now if you try and put (Though then connectionManager couldn't use it as-is)
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Happy to look at your proposed change. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed we should disallow explicitly setting |
||
return null; | ||
}; | ||
|
||
/** | ||
* Ensure valid auth credentials are present. This may rely in an already-known | ||
|
@@ -157,7 +194,7 @@ var Auth = (function() { | |
} | ||
callback(null, (self.tokenDetails = tokenResponse)); | ||
}); | ||
} | ||
}; | ||
|
||
if(token) { | ||
if(this._tokenClientIdMismatch(token.clientId)) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -458,18 +458,13 @@ var ConnectionManager = (function() { | |
this.setConnection(connectionId, connectionKey, connectionSerial); | ||
} | ||
|
||
var auth = this.realtime.auth; | ||
if(clientId && !(clientId === '*')) { | ||
if(auth.clientId && auth.clientId != clientId) { | ||
/* Should never happen in normal circumstances as realtime should | ||
* recognise mismatch and return an error */ | ||
var msg = 'Unexpected mismatch between expected and received clientId' | ||
var err = new ErrorInfo(msg, 40102, 401); | ||
Logger.logAction(Logger.LOG_ERROR, 'ConnectionManager.activateTransport()', msg); | ||
if(clientId) { | ||
var err = this.realtime.auth.setClientId(clientId); | ||
if(err) { | ||
Logger.logAction(Logger.LOG_ERROR, 'ConnectionManager.activateTransport()', err.message); | ||
transport.abort(err); | ||
return; | ||
} | ||
auth.clientId = clientId; | ||
} | ||
|
||
this.emit('transport.active', transport, connectionKey, transport.params); | ||
|
@@ -876,6 +871,15 @@ var ConnectionManager = (function() { | |
this.notifyState({state: 'closed'}); | ||
}; | ||
|
||
ConnectionManager.prototype.onAuthUpdated = function() { | ||
var state = this.state.state; | ||
if(state == 'connected' || state == 'connecting') { | ||
/* in the current protocol version we are not able to update auth params on the fly; | ||
* so disconnect, and the new auth params will be used for subsequent reconnection */ | ||
this.disconnectAllTransports(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I expect by doing this we'll trigger a disconnected state which in turn will:
I think both of these things are bad. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Well, that's because it is The way to avoid this is to implement upgrade in all of the other libraries, which I think we agreed would not happen. This is a temporary situation until we have in-protocol auth update. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, fine, we just need to document that then. Can you confirm that a WS connection would by default fallback to Comet though? That is not ideal. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes it will and it will do it for the same reasons that we don't currently cache the last successful transport. You might have a websocket connected over cellular, but by the time the reauth happens you're in the office on the office Wifi, where ws fails because of a proxy. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Sure, but why not try the same transport again and then fallback? I am reasonably confident that in most cases the transport that was used last could be used again because it's typically a device restriction as opposed to a network restriction. Whereas assuming it can't in most cases negatively impacts performance, adds more work on both ends, and is unlikely to happen that often. |
||
} | ||
}; | ||
|
||
ConnectionManager.prototype.disconnectAllTransports = function() { | ||
Logger.logAction(Logger.LOG_MINOR, 'ConnectionManager.disconnectAllTransports()', 'disconnecting all transports'); | ||
|
||
|
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 should maybe be
if('clientId' in options)
-- if someone tries to pass in{clientId: null}
,""
, orundefined
, setClientId should deal with that (whether by throwing an error or unsetting the clientId depending on whether we decide setOptions should be able to let you change your clientId)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, makes sense