The OSID Context is a form of a properties map that can be used to pass out-of-band information around the Interface. To the purist, the mention of the words around, Interface, and out-of-band not only spells trouble, but is downright evil.
The dilemma stems from the fact that OSIDs are Service Interfaces, not Java interfaces. It's just that when using Java, they happen to look like Java interfaces. The OSID attempts to define the semantics of a Service, not a particular Implementation. There's a sense that the Service Interface contains only common method definitions although many of these can be ignored for a particular Implementation. The problem arises when one Implementation needs to get its hands on the internals of another.
But the whole point of using OSIDs is that this shouldn't be possible. Yes, it should be avoided, but sometimes it can't be helped. The price paid, however, is that the Application becomes tied to the Implementation. As it turns out, that decision was already made before the OSIDs came along and sliding an Interace in there isn't the pixie dust that will instantly introduce interchangeability.
This issue comes up with the Authentication OSID. Generally, the Application invoking Authentication should be the Implementation of another OSID. This may not be true all the time and we shouldn't respect the Interface less just because we may have a situation with two Implementations conspiring. They are supposed to be modular too.
For example, we have an Implementation of the Scheduling OSID that
accesses data from a remote calendaring server. This server expects a
username and password sent inside an SSL-encrypted connection as part
of its own calendaring protocol. The Scheduling Implementation invokes
Authentication to get the username and password from the user with the
help of some pretty dialog window. Scheduling then needs to open an
SSL-encrypted connection and send the username/password pair. But the
only method available is authenticateUser().
One may be tempted to have Authentication send the username and password. After all, this is a detail of Authentication and should be kept under the Authentication Interface. Then Authentication needs to somehow get a hold of the socket that Scheduling created which is the same problem only in reverse. Many protocols don't easily separate transmission of authentication data from other data. These are done in the same step and so there's no place appropriate for an Interface. As it turns out, I keep Authentication Implementations away from protocols.
[diagram]Or, perhaps, there should be a method called
getPassword(). Then we need to define such methods for
every type of authentication and disenfranchise new mechanisms. Maybe
we can have one method called getSomeAuthenticationData()
that can return an object depending on what object needs to be
returned. There's using Interfaces and then there's pretending to use
Interfaces and guess which side this suggestion falls on. No, this
requires using that thing I swore I'd never use.
I'm sure somewhere I wrote that the OsidContext was evil. It still is. But it's a necessary evil. To be used oh so sparingly when all other alternatives have been exhausted. But why not pass an opaque object that can be cast into whatever object the Implementation requires? The answer may be simply a matter of taste. Just because it looks like a method doesn't mean it is an Interface. The object does not define what is passing through and is in itself an out-of-band agreement in method format. What is required for this case is an out-of-band agreement. I say, let's make it unambiguous and not fool ourselves into thinking we're doing anything more sophisticated than that.
It may appear that the plunge into the land of the out-of-band is a sure way to weld the Application and Implementation together. However, this need not be an all or nothing proposition. It may simply be the case the welding occurred before you got there and the Implementation is simply reflecting how a system already works (as opposed to how it might work if the system itself was designed according to these principles).
In my experiences so far, I've only found the need for the OsidContext in two cases. One is getting authentication data out of the Implementation and the other is getting it back in. It may very well be that the OsidContext could be reduced in scope to AuthenticationContext, but it would have to be available to all the OSIDs. Consider a servlet whereby authentication data is buried somewhere within the HttpRequest. The servlet calls Authorization which in turns loads Authentication (the servlet should not call these separately if the job it needs to do is authorize). The HttpRequest needs to be handed through Authorization to make it available to Authentication.
Is it valid to have an OSID http aware? Why not? If an Implementation can pop up dialog boxes and log to the tty, there's no reason it couldn't participate in web page output. Sometimes the OSIDs are looked upon as if they are low level utility libraries. They can be implemented in that way but that's ignoring the wider set of possibilities if they are looked upon as Services. You just have to know what Service you are getting from a given Implementation.
Another aspect of interchangeability. There's Specification compliance but this alone doesn't guarantee interchangeability. At another level the Implementation, while compliant, needs to do the job that is expected of it. If my company uses LDAP for identifying people I need to use an LDAP-based Agent Implementation. While I can load a PeopleSoft version and have that work at a code level, I can't expect it to do the job.
Somewhere in between is that the out-of-band agreements must also be in alignment between the Application and the Implementation. Yes, these agreements such as defining Context elements, get in the way. If done correctly, the use of the Context should align with the restrictions of the underlying system.
For example, a server may require Kerberos authentication. An Implementation of Kerberos will be invoked and this Implementation makes a ticket available through its Context so the Application may send it to the server. Only Implementations that make use of the Context in the way the Application expects can be used by the Application. But only Implementations which do Kerberos can be used.
There's no definition surrounding the Context. There's no rule that prevents us from adding some. In fact, this is beginning to sound much like the Property identification problem.
If all password-based Authentication Implementations passed the password in the same way, and Kerberos Authentication Implementations passed tickets in the same way, and X.509 servlet implementations passed the HttpRequest the same way, then we would at least have interchangeability among like-Implementations.
We can create object identifiers to represent a specific Context element and assign some specific meaning to it.
| domain/identifier@authority | the name of the fully qualified principal authenticated |
| oid/1.3.6.1.4.122316.1.1.3.3.1.0@osid.org | the name of the fully qualified principal authenticated |
| oid/1.3.6.1.4.122316.1.1.3.3.2.0@osid.org | the password in clear text |
| oid/1.3.6.1.4.122316.1.1.3.3.20.1.0@osid.org | the HttpRequest object |
As with Properties, the domain and authority are included as part of the string to allow for other identification schemes. The important aspect is that there be some way to forge an agreement on the definition and meaning of a Context element and some place we can figure out what's been defined.