-2

Implementation 1

type XAuth{ // talking to source1
   field1 Type1
   field2 Type2 
}

func (d *XAuth) f1(x str){
  // do something
}

func (d *XAuth) f2(x, y int){
  // do something
}

Implementation 2

type YAuth { // talking to source2
   field1 Type3
   field2 Type4 
}

func (d *YAuth) g1(x []str){
  // do something
}

func (d *YAuth) g2(x, y str){
  // do something
}

Implementation 3

type ZAuth{ // talking to source3
   field1 Type4
   field2 Type5 
}

func (d *ZAuth) h1(x float64){
  // do something
}

func (d *ZAuth) h2(y int){
  // do something
}

func (d *ZAuth) h3(z str){
  // do something
}

User provides credentials user/passwd to validate with above 3 implementations. Iterate these implementations and accept the credentials if any of the above 3 implementations validate successfully.

How should the public API Auth(user,passwd)de-couple from these three different implementations? user of the public API provides user/passwd

overexchange
  • 15,768
  • 30
  • 152
  • 347

1 Answers1

1

I'd say you may follow the usual approach to implement such mechanisms: have the public API have "steps" in its operation, a "step" would be implemented as a method which would accept an "input" from the client and upon completion return an error, a possible "output" to the client and a boolean indicating whether the processing is over of carrying out the next step is required.

Something like

type ClientAuthenData interface {
}

type ServerAuthenData interface {
}

type Authenticator interface {
  Step(in ClientAuthenData) (out ServerAuthenData, err error, complete bool)
}

The interpretation of both the input and the output data depends on the concrete authenticator being used and the number of the step.

kostix
  • 51,517
  • 14
  • 93
  • 176
  • Does public API `Authenticate()` will call `Step ()` of every implementation? – overexchange Nov 25 '20 at 07:59
  • You won't have `Authenticate` in a public API, only `Step`. Basically, that's how any authentication protocol I'm familiar with, works: it's a series of exchanges with the server until the serer says "permitted" or "denied". Some advanced schemes also implement a way to negotiate a particular auth mech prior to the "main" exchange but looks like your API does not require that. You may just "rename" my `Step` to `Authenticate` if that'd make the idea "click" ;-) The ground principles are: 1) the client performs authentication "steps" until said it's all over; 2) what data comes out and in… – kostix Nov 25 '20 at 08:37
  • …at each step of carrying out the authentication process, depends on the mech in use. – kostix Nov 25 '20 at 08:39
  • So, do you mean, each implementation run as server? – overexchange Nov 25 '20 at 09:02
  • No, not at all, I just mean that I see no reason not _to model_ your API after the exchange a client of _an authentication protocol_ would perform when communicating with the server: anyway any of your concrete authenticators will eventually talk to some server (I have hard time imagining how would you perform LDAP authen without actually talking with a LDAP server—even though your code merely calls some other code to do that: somewhere down below all these layers of code something performs the real exchange over some sort of IPC). – kostix Nov 25 '20 at 09:48
  • Note that all of the above comes from two key points I have drawn form your question: 1) the client inevitably knows which "kind" of authentication takes place—as it anyway has to supply different kinds of data on each authentication step; 2) these bits of data are different for different kinds of authenticators, and the number of steps needed to be performed to complete the process may be different (two in all the cases you listed but who knows what may be required for a new protocol?). – kostix Nov 25 '20 at 09:58
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/225111/discussion-between-overexchange-and-kostix). – overexchange Nov 25 '20 at 16:56