...

Source file src/github.com/go-openapi/runtime/middleware/route_authenticator_test.go

Documentation: github.com/go-openapi/runtime/middleware

     1  package middleware
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net/http"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/go-openapi/runtime"
    12  )
    13  
    14  type countAuthenticator struct {
    15  	count     int
    16  	applies   bool
    17  	principal interface{}
    18  	err       error
    19  }
    20  
    21  func (c *countAuthenticator) Authenticate(_ interface{}) (bool, interface{}, error) {
    22  	c.count++
    23  	return c.applies, c.principal, c.err
    24  }
    25  
    26  func newCountAuthenticator(applies bool, principal interface{}, err error) *countAuthenticator {
    27  	return &countAuthenticator{applies: applies, principal: principal, err: err}
    28  }
    29  
    30  var (
    31  	successAuth = runtime.AuthenticatorFunc(func(_ interface{}) (bool, interface{}, error) {
    32  		return true, "the user", nil
    33  	})
    34  	failAuth = runtime.AuthenticatorFunc(func(_ interface{}) (bool, interface{}, error) {
    35  		return true, nil, errors.New("unauthenticated")
    36  	})
    37  	noApplyAuth = runtime.AuthenticatorFunc(func(_ interface{}) (bool, interface{}, error) {
    38  		return false, nil, nil
    39  	})
    40  )
    41  
    42  func TestAuthenticateSingle(t *testing.T) {
    43  	ra := RouteAuthenticator{
    44  		Authenticator: map[string]runtime.Authenticator{
    45  			"auth1": successAuth,
    46  		},
    47  		Schemes: []string{"auth1"},
    48  		Scopes:  map[string][]string{"auth1": nil},
    49  	}
    50  	ras := RouteAuthenticators([]RouteAuthenticator{ra})
    51  
    52  	require.False(t, ras.AllowsAnonymous())
    53  
    54  	req, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
    55  	route := &MatchedRoute{}
    56  	ok, prin, err := ras.Authenticate(req, route)
    57  	require.NoError(t, err)
    58  	require.True(t, ok)
    59  	require.Equal(t, "the user", prin)
    60  
    61  	require.Equal(t, ra, *route.Authenticator)
    62  }
    63  
    64  func TestAuthenticateLogicalOr(t *testing.T) {
    65  	ra1 := RouteAuthenticator{
    66  		Authenticator: map[string]runtime.Authenticator{
    67  			"auth1": noApplyAuth,
    68  		},
    69  		Schemes: []string{"auth1"},
    70  		Scopes:  map[string][]string{"auth1": nil},
    71  	}
    72  	ra2 := RouteAuthenticator{
    73  		Authenticator: map[string]runtime.Authenticator{
    74  			"auth2": successAuth,
    75  		},
    76  		Schemes: []string{"auth2"},
    77  		Scopes:  map[string][]string{"auth2": nil},
    78  	}
    79  	// right side matches
    80  	ras := RouteAuthenticators([]RouteAuthenticator{ra1, ra2})
    81  	require.False(t, ras.AllowsAnonymous())
    82  
    83  	req, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
    84  	route := &MatchedRoute{}
    85  	ok, prin, err := ras.Authenticate(req, route)
    86  	require.NoError(t, err)
    87  	require.True(t, ok)
    88  	require.Equal(t, "the user", prin)
    89  
    90  	require.Equal(t, ra2, *route.Authenticator)
    91  
    92  	// left side matches
    93  	ras = RouteAuthenticators([]RouteAuthenticator{ra2, ra1})
    94  	require.False(t, ras.AllowsAnonymous())
    95  
    96  	req, _ = http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
    97  	route = &MatchedRoute{}
    98  	ok, prin, err = ras.Authenticate(req, route)
    99  	require.NoError(t, err)
   100  
   101  	require.True(t, ok)
   102  	require.Equal(t, "the user", prin)
   103  	require.Equal(t, ra2, *route.Authenticator)
   104  }
   105  
   106  func TestAuthenticateLogicalAnd(t *testing.T) {
   107  	ra1 := RouteAuthenticator{
   108  		Authenticator: map[string]runtime.Authenticator{
   109  			"auth1": noApplyAuth,
   110  		},
   111  		Schemes: []string{"auth1"},
   112  		Scopes:  map[string][]string{"auth1": nil},
   113  	}
   114  	authorizer := newCountAuthenticator(true, "the user", nil)
   115  	ra2 := RouteAuthenticator{
   116  		Authenticator: map[string]runtime.Authenticator{
   117  			"auth2": authorizer,
   118  			"auth3": authorizer,
   119  		},
   120  		Schemes: []string{"auth2", "auth3"},
   121  		Scopes:  map[string][]string{"auth2": nil},
   122  	}
   123  	ras := RouteAuthenticators([]RouteAuthenticator{ra1, ra2})
   124  	require.False(t, ras.AllowsAnonymous())
   125  
   126  	req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
   127  	require.NoError(t, err)
   128  	route := &MatchedRoute{}
   129  	ok, prin, err := ras.Authenticate(req, route)
   130  	require.NoError(t, err)
   131  	require.True(t, ok)
   132  	require.Equal(t, "the user", prin)
   133  
   134  	require.Equal(t, ra2, *route.Authenticator)
   135  	require.Equal(t, 2, authorizer.count)
   136  
   137  	var count int
   138  	successA := runtime.AuthenticatorFunc(func(_ interface{}) (bool, interface{}, error) {
   139  		count++
   140  		return true, "the user", nil
   141  	})
   142  	failA := runtime.AuthenticatorFunc(func(_ interface{}) (bool, interface{}, error) {
   143  		count++
   144  		return true, nil, errors.New("unauthenticated")
   145  	})
   146  
   147  	ra3 := RouteAuthenticator{
   148  		Authenticator: map[string]runtime.Authenticator{
   149  			"auth2": successA,
   150  			"auth3": failA,
   151  			"auth4": successA,
   152  		},
   153  		Schemes: []string{"auth2", "auth3", "auth4"},
   154  		Scopes:  map[string][]string{"auth2": nil},
   155  	}
   156  	ras = RouteAuthenticators([]RouteAuthenticator{ra1, ra3})
   157  
   158  	require.False(t, ras.AllowsAnonymous())
   159  
   160  	req, _ = http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
   161  	route = &MatchedRoute{}
   162  	ok, prin, err = ras.Authenticate(req, route)
   163  	require.Error(t, err)
   164  	require.True(t, ok)
   165  	require.Nil(t, prin)
   166  
   167  	require.Equal(t, ra3, *route.Authenticator)
   168  	require.Equal(t, 2, count)
   169  
   170  	ra4 := RouteAuthenticator{
   171  		Authenticator: map[string]runtime.Authenticator{
   172  			"auth2": successA,
   173  			"auth3": successA,
   174  			"auth4": failA,
   175  		},
   176  		Schemes: []string{"auth2", "auth3", "auth4"},
   177  		Scopes:  map[string][]string{"auth2": nil},
   178  	}
   179  	ras = RouteAuthenticators([]RouteAuthenticator{ra1, ra4})
   180  
   181  	require.False(t, ras.AllowsAnonymous())
   182  
   183  	req, _ = http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
   184  	route = &MatchedRoute{}
   185  	ok, prin, err = ras.Authenticate(req, route)
   186  	require.Error(t, err)
   187  	require.True(t, ok)
   188  	require.Nil(t, prin)
   189  
   190  	require.Equal(t, ra4, *route.Authenticator)
   191  	require.Equal(t, 5, count)
   192  }
   193  
   194  func TestAuthenticateOptional(t *testing.T) {
   195  	ra1 := RouteAuthenticator{
   196  		Authenticator: map[string]runtime.Authenticator{
   197  			"auth1": noApplyAuth,
   198  		},
   199  		Schemes: []string{"auth1"},
   200  		Scopes:  map[string][]string{"auth1": nil},
   201  	}
   202  	ra2 := RouteAuthenticator{
   203  		allowAnonymous: true,
   204  		Schemes:        []string{""},
   205  		Scopes:         map[string][]string{"": {}},
   206  	}
   207  
   208  	ra3 := RouteAuthenticator{
   209  		Authenticator: map[string]runtime.Authenticator{
   210  			"auth2": noApplyAuth,
   211  		},
   212  		Schemes: []string{"auth2"},
   213  		Scopes:  map[string][]string{"auth2": nil},
   214  	}
   215  
   216  	ras := RouteAuthenticators([]RouteAuthenticator{ra1, ra2, ra3})
   217  	require.True(t, ras.AllowsAnonymous())
   218  
   219  	req, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
   220  	route := &MatchedRoute{}
   221  	ok, prin, err := ras.Authenticate(req, route)
   222  	require.NoError(t, err)
   223  	require.True(t, ok)
   224  	require.Nil(t, prin)
   225  
   226  	require.Equal(t, ra2, *route.Authenticator)
   227  
   228  	ra4 := RouteAuthenticator{
   229  		Authenticator: map[string]runtime.Authenticator{
   230  			"auth1": noApplyAuth,
   231  		},
   232  		Schemes: []string{"auth1"},
   233  		Scopes:  map[string][]string{"auth1": nil},
   234  	}
   235  	ra5 := RouteAuthenticator{
   236  		allowAnonymous: true,
   237  	}
   238  
   239  	ra6 := RouteAuthenticator{
   240  		Authenticator: map[string]runtime.Authenticator{
   241  			"auth2": failAuth,
   242  		},
   243  		Schemes: []string{"auth2"},
   244  		Scopes:  map[string][]string{"auth2": nil},
   245  	}
   246  
   247  	ras = RouteAuthenticators([]RouteAuthenticator{ra4, ra5, ra6})
   248  	require.True(t, ras.AllowsAnonymous())
   249  
   250  	req, _ = http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
   251  	route = &MatchedRoute{}
   252  	ok, prin, err = ras.Authenticate(req, route)
   253  	require.Error(t, err)
   254  	require.True(t, ok)
   255  	require.Nil(t, prin)
   256  
   257  	require.Equal(t, ra6, *route.Authenticator)
   258  }
   259  

View as plain text