Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/oauth2-proxy/mockoidc
A Mock OIDC Server for Unit & Integration Tests
https://github.com/oauth2-proxy/mockoidc
golang oauth2 oidc
Last synced: about 1 month ago
JSON representation
A Mock OIDC Server for Unit & Integration Tests
- Host: GitHub
- URL: https://github.com/oauth2-proxy/mockoidc
- Owner: oauth2-proxy
- License: mit
- Created: 2021-02-01T21:10:07.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2024-02-16T22:23:30.000Z (10 months ago)
- Last Synced: 2024-06-18T15:22:45.665Z (6 months ago)
- Topics: golang, oauth2, oidc
- Language: Go
- Homepage:
- Size: 55.7 KB
- Stars: 58
- Watchers: 4
- Forks: 38
- Open Issues: 22
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# mockoidc
A Mock OpenID Connect Server for Authentication Unit and Integration Tests.
Created by @NickMeves and @egrif during the [Greenhouse Software](https://medium.com/in-the-weeds)
2021 Q1 Hack Day.[![Go Report Card](https://goreportcard.com/badge/github.com/oauth2-proxy/mockoidc)](https://goreportcard.com/report/github.com/oauth2-proxy/mockoidc)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
[![Maintainability](https://api.codeclimate.com/v1/badges/99c0561090d1002dc7e3/maintainability)](https://codeclimate.com/github/oauth2-proxy/mockoidc/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/99c0561090d1002dc7e3/test_coverage)](https://codeclimate.com/github/oauth2-proxy/mockoidc/test_coverage)## Usage
Import the package
```
import "github.com/oauth2-proxy/mockoidc"
```Start the MockOIDC Server. This will spin up a minimal OIDC server in its own
goroutine. It will listen on localhost on a random port.Then pull its configuration to integrate it with your application. Begin
testing!```
m, _ := mockoidc.Run()
defer m.Shutdown()cfg := m.Config()
// type Config struct {
// ClientID string
// ClientSecret string
// Issuer string
//
// AccessTTL time.Duration
// RefreshTTL time.Duration
// }
```### RunTLS
Alternatively, if you provide your own `tls.Config`, the server can run with
TLS:```
tlsConfig = &tls.Config{
// ...your TLS settings
}m, _ := mockoidc.RunTLS(tlsConfig)
defer m.Shutdown()
```### Endpoints
The following endpoints are implemented. They can either be pulled from the
OIDC discovery document (`m.Issuer() + "/.well-known/openid-configuration`)
or retrieved directly from the MockOIDC server.```
m, _ := mockoidc.Run()
defer m.Shutdown()m.Issuer()
m.DiscoveryEndpoint()
m.AuthorizationEndpoint()
m.TokenEndpoint()
m.UserinfoEndpoint()
m.JWKSEndpoint()
```### Seeding Users and Codes
By default, calls to the `authorization_endpoint` will start a session as if
the `mockoidc.DefaultUser()` had logged in, and it will return a random code
for the `token_endpoint`. The User in the session started by this call to the
`authorization_endpoint` will be the one in the tokens returned by the
subsequent `token_endpoint` call.These can be seeded with your own test Users & codes that will be returned:
```
m, _ := mockoidc.Run()
defer m.Shutdown()user := &mockoidc.User{
// User details...
}// Add the User to the queue, this will be returned by the next login
m.QueueUser(user)// Preset the code returned by the next login
m.QueueCode("12345")// ...Request to m.AuthorizationEndpoint()
```### Forcing Errors
Arbitrary errors can also be queued for handlers to return instead of their
default behavior:```
m, err := mockoidc.Run()
defer m.Shutdown()m.QueueError(&mockoidc.ServerError{
Code: http.StatusInternalServerError,
Error: mockoidc.InternalServerError,
Description: "Some Custom Description",
})
```### Manipulating Time
To accurately test token expiration scenarios, the MockOIDC server's view of
time is completely mutable.You can override the server's view of `time.Now`
```
mockoidc.NowFunc = func() { //...custom logic }
```As tests are running, you can fast-forward time to critical test points (e.g.
Access & Refresh Token expirations).```
m, _ := mockoidc.Run()m.FastForward(time.Duration(1) * time.Hour)
```#### Synchronizing with `jwt-go` time
Even though we can fast-forward time, the underlying tokens processed by the
[jwt-go](https://github.com/dgrijalva/jwt-go) library still have timing logic.We need to synchronize our timer with theirs:
```
m, _ := mockoidc.Run()
defer m.Shutdown()// Overrides jwt.TimeFunc to m.Now
reset := m.Synchronize()// reset is a mockoidc.ResetTime function that reverts jwt.TimeFunc to
// its original state
defer reset()
```### Manual Configuration
Everything started up with `mockoidc.Run()` can be done manually giving the
opportunity to finely tune the settings:```
// Create a fresh RSA Private Key for token signing
rsaKey, _ := rsa.GenerateKey(rand.Reader, 2048)// Create an unstarted MockOIDC server
m, _ := mockoidc.NewServer(rsaKey)// Create the net.Listener on the exact IP:Port you want
ln, _ := net.Listen("tcp", "127.0.0.1:8080")tlsConfig = &tls.Config{
// ...your TLS settings
}// tlsConfig can be nil if you want HTTP
m.Start(ln, tlsConfig)
defer m.Shutdown()
```Nearly all the MockOIDC struct is public. If you want to update any settings
to predefined values (e.g. `clientID`, `clientSecret`, `AccessTTL`,
`RefreshTTL`) you can before calling `m.Start`.Additional internal components of the MockOIDC server are public if you need
to tamper with them as well:```
type MockOIDC struct {
// ...other stuff// Normally, these would be private. Expose them publicly for
// power users.
Server *http.Server
Keypair *Keypair
SessionStore *SessionStore
UserQueue *UserQueue
ErrorQueue *ErrorQueue
}
```#### Adding Middleware
When configuring the MockOIDC server manually, you have the opportunity to add
custom middleware before starting the server (e.g. request logging, test
validators, etc).```
m, _ := mockoidc.NewServer(nil)middleware := func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
// custom middleware logic here...
next.ServeHTTP(rw, req)
// custom middleware logic here...
})
}m.AddMiddleware(middleware)
```