• Stars
    star
    238
  • Rank 169,306 (Top 4 %)
  • Language
    Kotlin
  • License
    MIT License
  • Created almost 5 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A scriptable/customizable web server for testing HTTP clients using OAuth2/OpenID Connect or applications with a dependency to a running OAuth2 server (i.e. APIs requiring signed JWTs from a known issuer)

Build Maven Central

As of version 0.3.3 the Docker image is published to the GitHub Container Registry and thus can be pulled anonymously from ghcr.io/navikt/mock-oauth2-server:<version>. Update your image pulling spells accordingly.

mock-oauth2-server

A scriptable/customizable web server for testing HTTP clients using OAuth2/OpenID Connect or applications with a dependency to a running OAuth2 server (i.e. APIs requiring signed JWTs from a known issuer). The server also provides the necessary endpoints for token validation (endpoint for JWKS) and ID Provider metadata discovery ("well-known" endpoints providing server metadata)

mock-oauth2-server is written in Kotlin using the great OkHttp MockWebServer as the underlying server library and can be used in unit/integration tests in both Java and Kotlin or in any language as a standalone server in e.g. docker-compose.

Even though the server aims to be compliant with regards to the supported OAuth2/OpenID Connect specifications, you should never use it for anything else than tests. That being said, when developing OAuth2 clients you should always verify that the expected requests are being made in your tests.

Motivation

The motivation behind this library is to provide a setup such that application developers don't feel the need to disable security in their apps when running tests! If you have any issues with regards to OAuth2 and tokens et. al. and consider to disable "security" when running tests please submit an issue or a PR so that we can all help developers and security to live in harmony once again (if ever..)!

Features

  • Multi-issuer/Multi-tenancy support: the server can represent as many different Identity Providers/Token Issuers as you need (with different token issuer names) WITHOUT any setup!
  • Implements OAuth2/OpenID Connect grants/flows
    • OpenID Connect Authorization Code Flow
    • OAuth2 Client Credentials Grant
    • OAuth2 JWT Bearer Grant (On-Behalf-Of flow)
    • OAuth2 Token Exchange Grant
    • OAuth2 Refresh Token Grant
    • OAuth2 Resource Owner Password Credentials (Password Grant)
      • usage should be avoided if possible as this grant is considered insecure and removed in its entirety from OAuth 2.1
  • Issued JWT tokens are verifiable through standard mechanisms with OpenID Connect Discovery / OAuth2 Authorization Server Metadata
  • Unit/Integration test support
    • Start and stop server for each test
    • Sane defaults with minimal setup if you don't need token customization
    • Enqueue expected tokens if you need to customize token claims
    • Enqueue expected responses
    • Verify expected requests made to the server
    • Customizable through exposure of underlying OkHttp MockWebServer
  • Standalone support - i.e. run as application in IDE, run inside your app, or as a Docker image (provided)
  • OAuth2 Client Debugger - e.g. support for triggering OIDC Auth Code Flow and receiving callback in debugger app, view token response from server (intended for standalone support)

API Documentation

mock-oauth2-server

📦 Install

Gradle Kotlin DSL

Latest version Maven Central

testImplementation("no.nav.security:mock-oauth2-server:$mockOAuth2ServerVersion")

Maven

Latest version Maven Central

<dependency>
  <groupId>no.nav.security</groupId>
  <artifactId>mock-oauth2-server</artifactId>
  <version>${mock-oauth2-server.version}</version>
  <scope>test</scope>
</dependency>

Docker

Latest version GitHub release (latest SemVer including pre-releases)

docker pull ghcr.io/navikt/mock-oauth2-server:$MOCK_OAUTH2_SERVER_VERSION

⌨️ Usage

Well-Known Configuration

The mock-oauth2-server will supply different configurations depending on the url used against the server, more specifically the first path (or context root) element in your request url will specify the issuerId.

A request to http://localhost:8080/default/.well-known/openid-configuration will yield an issuerId of default with the following configuration:

{
   "issuer":"http://localhost:8080/default",
   "authorization_endpoint":"http://localhost:8080/default/authorize",
   "token_endpoint":"http://localhost:8080/default/token",
   "userinfo_endpoint":"http://localhost:8080/default/userinfo",
   "jwks_uri":"http://localhost:8080/default/jwks",
   "introspection_endpoint":"http://localhost:8080/default/introspect",
   "response_types_supported":[
      "query",
      "fragment",
      "form_post"
   ],
   "subject_types_supported":[
      "public"
   ],
   "id_token_signing_alg_values_supported":[
     "ES256",
     "ES384",
     "RS256",
     "RS384",
     "RS512",
     "PS256",
     "PS384",
     "PS512"
   ]
}

The actual issuer value in a JWT will be iss: "http://localhost:8080/default"

To use another issuer with id anotherissuer simply make a request to http://localhost:8080/anotherissuer/.well-known/openid-configuration and the configuration will change accordingly.

Unit tests

Setup test
  • Start the server at a random port
  • Get url for server metadata/configuration
  • Setup your app to use the OAuth2 server metadata and conduct your tests
  • Shutdown the server
val server = MockOAuth2Server()
server.start()
// Can be anything you choose - should uniquely identify your issuer if you have several
val issuerId = "default"
// Discovery url to authorization server metadata
val wellKnownUrl = server.wellKnownUrl(issuerId).toString()
// ......
// Setup your app with metadata from wellKnownUrl and do your testing here
// ......
server.shutdown()
Testing an app requiring user login with OpenID Connect Authorization Code Flow
  • Setup test like above
  • Make your test HTTP client follow redirects
  • Your callback (redirect_uri) endpoint should receive the callback request as required and be able to retrieve a token from the token endpoint.

If you need to get a login for a specific user you can use the OAuth2TokenCallback interface to provide your own or set values in the DefaultOAuth2TokenCallback

@Test
fun loginWithIdTokenForSubjectFoo() {
    server.enqueueCallback(
        DefaultOAuth2TokenCallback(
            issuerId = issuerId,
            subject = "foo"
        )
    )
  // Invoke your app here and assert user foo is logged in
}

If you need specific claims in the resulting id_token - e.g. acr or a custom claim you can also use the OAuth2TokenCallback:

@Test
fun loginWithIdTokenForAcrClaimEqualsLevel4() {
    server.enqueueCallback(
        DefaultOAuth2TokenCallback(
            issuerId = issuerId,
            claims = mapOf("acr" to "Level4")
        )
    )
  // Invoke your app here and assert acr=Level4 is present in id_token
}
Testing an API requiring access_token (e.g. a signed JWT)
val token: SignedJWT = oAuth2Server.issueToken(issuerId, "someclientid", DefaultOAuth2TokenCallback())
//use your favourite HTTP client to invoke your API and attach the serialized token
val request = // ....
request.addHeader("Authorization", "Bearer ${token.serialize()}")
More examples

Have a look at some examples in both Java and Kotlin in the src/test directory:

API

Server URLs

You can retrieve URLs from the server with the correct port and issuerId etc. by invoking one of the fun *Url(issuerId: String): HttpUrl functions/methods:

val server = MockOAuth2Server()
server.start()
val wellKnownUrl = server.wellKnownUrl("yourissuer")
// will result in the following url:
// http://localhost:<a random port>/yourissuer/.well-known/openid-configuration

Standalone server

The standalone server will default to port 8080 and can be started by invoking main() in StandaloneMockOAuth2Server.kt (in kotlin) or StandaloneMockOAuth2ServerKt (in Java)

On Windows, it's easier to run the server in docker while specifying the host as localhost, e.g. docker run -p 8080:8080 -h localhost $IMAGE_NAME

Note If you want to check if the server is up and running you can visit /isalive and see if you get a 200 in return.

Configuration

The standalone server supports the following configuration by ENV variables:

Variable Description
SERVER_HOSTNAME Lets the standalone server bind to a specific hostname, by default it binds to 0.0.0.0
SERVER_PORT or PORT The port that the standalone server will listen to, defaults to 8080. The PORT environment variable may be used to run the Docker image on Heroku as per the documentation here.
JSON_CONFIG_PATH The absolute path to a json file containing configuration about the OAuth2 part of the server (OAuth2Config). More details on the format below.
JSON_CONFIG The actual JSON content of OAuth2Config, this ENV var takes precedence over the JSON_CONFIG_PATH var. More details on the format below.
LOG_LEVEL How verbose the root logging output is, defaults to INFO
JSON_CONFIG

The JSON_CONFIG lets you configure the contents of the OAuth2Config class using JSON.

Example:

{
    "interactiveLogin": true,
    "httpServer": "NettyWrapper",
    "tokenCallbacks": [
        {
            "issuerId": "issuer1",
            "tokenExpiry": 120,
            "requestMappings": [
                {
                    "requestParam": "scope",
                    "match": "scope1",
                    "claims": {
                        "sub": "subByScope",
                        "aud": [
                            "audByScope"
                        ]
                    }
                }
            ]
        },
        {
            "issuerId": "issuer2",
            "requestMappings": [
                {
                    "requestParam": "someparam",
                    "match": "somevalue",
                    "claims": {
                        "sub": "subBySomeParam",
                        "aud": [
                            "audBySomeParam"
                        ]
                    }
                }
            ]
        }
    ]
}

A token provider can support different signing algorithms. Configure your token provider and add this to your config with preferred JWS algorithm:

{
  "tokenProvider" : {
    "keyProvider" : {
      "algorithm" : "ES256"
    }
  }
}
Property Description
interactiveLogin true or false, enables login screen when redirecting to server /authorize endpoint
loginPagePath An optional string refering to a html file that is served as login page. This page needs to contain a form that posts a username and optionally a claims field. See src/test/resource/login.example.html as an example.
httpServer A string identifying the httpserver to use. Must match one of the following enum values: MockWebServerWrapper or NettyWrapper
tokenCallbacks A list of RequestMappingTokenCallback that lets you specify which token claims to return when a token request matches the specified condition.

From the JSON example above:

A token request to http://localhost:8080/issuer1/token with parameter scope equal to scope1 will match the first tokenCallback:

{
    "issuerId": "issuer1",
    "tokenExpiry": 120,
    "requestMappings": [
        {
            "requestParam": "scope",
            "match": "scope1",
            "claims": {
                "sub": "subByScope",
                "aud": [
                    "audByScope"
                ]
            }
        }
    ]
}

and return a token response containing a token with the following claims:

{
  "sub": "subByScope",
  "aud": "audByScope",
  "nbf": 1616416942,
  "iss": "http://localhost:54905/issuer1",
  "exp": 1616417062,
  "iat": 1616416942,
  "jti": "28697333-6f25-4b1f-b2c2-409ce010933a"
}

Docker

Build to local docker daemon

./gradlew -Djib.from.platforms=linux/amd64 jibDockerBuild # or alternatively -Djib.from.platforms=linux/arm64 for ARM64

Run container

docker run -p 8080:8080 $IMAGE_NAME

Docker-Compose

In order to get container-to-container networking to work smoothly alongside browser interaction you must specify a host entry in your hosts file, 127.0.0.1 host.docker.internal and set hostname in the mock-oauth2-server service in your docker-compose.yaml file:

version: '3.7'
services:
  your_app:
    build: .
    ports:
      - 8080:8080
  mock-oauth2-server:
    image: ghcr.io/navikt/mock-oauth2-server:$MOCK_OAUTH2_SERVER_VERSION
    ports:
      - 8080:8080
    hostname: host.docker.internal

Debugger

The debugger is a OAuth2 client implementing the authorization_code flow with a UI for debugging (e.g. request parameters). Point your browser to http://localhost:8080/default/debugger to check it out.

Enabling HTTPS

In order to enable HTTPS you can either provide your own keystore or let the server generate one for you.

Unit tests

You need to supply the server with an SSL config, in order to do that you must specify your chosen server type in OAuth2Config and pass in the SSL config to your server.

Generate keystore:

val ssl = Ssl()
val server = MockOAuth2Server(
    OAuth2Config(httpServer = MockWebServerWrapper(ssl))
)

This will generate a SSL certificate for localhost and can be added to your client's truststore by getting the ssl config: ssl.sslKeystore.keyStore

Bring your own:

val ssl = Ssl(
    SslKeystore(
        keyPassword = "",
        keystoreFile = File("src/test/resources/localhost.p12"),
        keystorePassword = "",
        keystoreType = SslKeystore.KeyStoreType.PKCS12
    )
)
val server = MockOAuth2Server(
    OAuth2Config(httpServer = MockWebServerWrapper(ssl))
)

Docker / Standalone mode - JSON_CONFIG

In order to enable HTTPS for the server in Docker or standalone mode you can either make the server generate the keystore or bring your own.

Generate keystore:

{
  "httpServer" : {
    "type" : "NettyWrapper",
    "ssl" : {}
  }
}

Bring your own:

{
    "httpServer" : {
        "type" : "NettyWrapper",
        "ssl" : {
            "keyPassword" : "",
            "keystoreFile" : "src/test/resources/localhost.p12",
            "keystoreType" : "PKCS12",
            "keystorePassword" : "" 
        }
    }
}

Upgrading the gradle wrapper

Find the newest version of gradle here: https://gradle.org/releases/ Then run this command: ./gradlew wrapper --gradle-version $gradleVersion

Remeber to also update the gradle version in the build.gradle.kts file gradleVersion = "$gradleVersion"

👥 Contact

This project is currently maintained by the organisation @navikt.

If you need to raise an issue or question about this library, please create an issue here and tag it with the appropriate label.

For contact requests within the @navikt org, you can use the Slack channel #pig_sikkerhet

If you need to contact anyone directly, please see contributors.

✏️ Contributing

To get started, please fork the repo and checkout a new branch. You can then build the library with the Gradle wrapper

./gradlew build

See more info in CONTRIBUTING.md

⚖️ License

This library is licensed under the MIT License

More Repositories

1

aksel

NAVs designsystem og Aksel-portalen
TypeScript
122
star
2

DSF

Det Sentrale Folketrygdsystemet
COBOL
52
star
3

offentlig

Retningslinjer for åpen kildekode i NAV
44
star
4

rapids-and-rivers

Rapids and rivers concept based on ideas of Fred George @fredgeorge
Kotlin
24
star
5

kafka-plain-saslserver-2-ad

Enhancing Kafka security, PlainSaslServer with LDAP binding and SimpleAclAuthorizer with LDAP group membership
Kotlin
20
star
6

github-app-token-generator

GitHub action for generating an installation token for a GitHub App
Shell
19
star
7

arxaas

ARXaaS is a "Anonymization as a Service" project built ontop of the ARX library
Java
17
star
8

fnrvalidator

JavaScript-kode som validerer gyldigheten av norske fødsels- og D-nummer
TypeScript
17
star
9

token-support

Modules to support security token handling in NAV
Kotlin
15
star
10

pdfgen

Simple application for generating PDFs
Kotlin
14
star
11

pam-public-feed

Public JSON feed for job ads
Kotlin
14
star
12

kafka-sandbox

Experiments with Kafka clients and Spring Kafka. Demo code and tutorials.
Java
13
star
13

nav-faker

nav-faker er et bibliotek som lar deg generere opp norske testdata.
TypeScript
13
star
14

security-playbook

Security Playbook for NAV IT
JavaScript
13
star
15

vtp

Virtuell tjenesteplattform
Java
11
star
16

laundromat

Python
10
star
17

aksel-website

Aksel + Designsystemet sin dokumentasjon
TypeScript
10
star
18

accessibility-reporting-tool

App for rapportering av tilgjengelighet fra team på NAV sine sider
Kotlin
9
star
19

opendistro-elasticsearch

Helm chart for Open Distro For Elasticsearch
Shell
9
star
20

familie-ba-sak

Applikasjon for saksbehandling av barnetrygd
Kotlin
9
star
21

common-java-modules

Common Java libraries to streamline backend development
Java
9
star
22

kafka-embedded-env

Simple API for starting up a Kafka environment in Kotlin or Java
Kotlin
8
star
23

pyarxaas

Python
8
star
24

modiapersonoversikt

Modiapersonoversikt er en intern arbeidsflate som gir veiledere og saksbehandlere oversikt over brukeres forhold til NAV.
TypeScript
8
star
25

ai-lab-spacy-bokmaal

Norwegian language model for spaCy
Python
8
star
26

nav-dekoratoren

Header og footer på nav.no
TypeScript
8
star
27

Designsystemet-old

Designsystem-teamet i NAV sitt offisielle område på Github
8
star
28

crm-hot

Salesforce-pakke brukt av Tolketjenesten i Hjelpemidler og tilrettelegging for bestilling, fordeling og gjennomføring av tolkeoppdrag.
Apex
8
star
29

baseimages

Base images for Docker
Dockerfile
7
star
30

amplitude-proxy

Application that whitelists and forwards traffic to amplitudes servers.
JavaScript
7
star
31

yaml-validator

Validates YAML documents against a given schema
Python
7
star
32

nada

NADA - Dokumentasjon
HTML
6
star
33

muckscan

Simple Docker-based tool for scanning git repositories for bad history.
Go
6
star
34

tjenestespesifikasjoner

WSDL-er og XML-spesifikasjoner for hvordan webtjenester i NAV snakker sammen.
XSLT
6
star
35

foreldrepengesoknad

Selvbetjeningsløsning for søknad om foreldrepenger
TypeScript
6
star
36

skjemabygging-formio

Skjemabygger for skjemadigitalisering i NAV
TypeScript
6
star
37

skjemautfylling-formio

JavaScript
6
star
38

nav-enonicxp-frontend

Frontend for åpne sider på nav.no
TypeScript
5
star
39

testnorge

Applikasjoner for orkestering av syntetiske testdata for fagsystemer i nav.
Java
5
star
40

foreldrepengesoknad-api

API for brukerrettede foreldrepengetjenester
Java
5
star
41

veilarbportefoljeflatefs

Oversikt for veiledere over oppfølgingsbrukere
TypeScript
5
star
42

ab-test

GitHub Actions for A/B-Testing
JavaScript
5
star
43

eessi-pensjon-journalforing

Journalfører SED når kafka meldinger konsumeres
Kotlin
5
star
44

fhir

FHIR Implementation Guides by the Norwegian Labour and Welfare Administration (NAV)
CSS
5
star
45

crm-arbeidsgiver-base

Salesforce-pakke fra produktområde Arbeidsgiver
Apex
5
star
46

eessi-pensjon-fagmodul

EESSI pensjon fagmodul
Kotlin
5
star
47

veilarbregistrering

Applikasjon for nyregistrering av arbeidssøkere.
Kotlin
5
star
48

helse-spleis

Automatisk saksbehandling av sykepenger
Kotlin
5
star
49

sykefravarsstatistikk

Frontend for sykefraværsstatistikk
TypeScript
5
star
50

fpsak-frontend

Frontend kode for vl-foreldrepenger
JavaScript
5
star
51

frontend

Samling for gode frontend løsninger, golden-path for frontend-prosjekter
TypeScript
5
star
52

skjemapublisering

Repository for å "publisere" skjemaer fra byggeren til utfylleren
JavaScript
5
star
53

fp-formidling

Bestiller Dokumenter og Brev for foreldrepenger
Java
5
star
54

Sikkerhetsprosess

Dette repoet skal inneholde informasjon om hvordan sikkerhetsprosessen er i NAV IT. Det vil si prosess rundt risikovurderinger, klassifiseringer med mer.
5
star
55

remove-package-versions

GitHub Action that can be used to remove older versions of a package from GitHub Packages
PHP
5
star
56

sosialhjelp-soknad

Søknad for økonomisk sosialhjelp
TypeScript
4
star
57

helse-speil

Innsyn i saksbehandling av sykepenger
TypeScript
4
star
58

stub-oidc-provider

Simple OIDC provider which accepts all logins and creates a ID token (for testing purposes)
JavaScript
4
star
59

detsombetyrnoe

TypeScript
4
star
60

soknadsveiviser

Søknadsveiviseren på nav.no
TypeScript
4
star
61

diasight

Ny pasientjournal løsning for Team Helseopplysninger
TypeScript
4
star
62

spsak

Kopi (versjon 2) av FPSAK (Foreldrepenger) som skal bli SPSAK (Sykepenger)
Java
4
star
63

aktivitetsplan

Aktivitetsplanen for brukere i NAV
TypeScript
4
star
64

pensjon-etterlatte

TypeScript
4
star
65

polly

Java
4
star
66

vl-jenkins

Jenkins pipeline scripts
Groovy
4
star
67

veilarbportefolje

Tjeneste som aggregerer data fra andre baksystemer og håndterer oppdatering av søkeindeks brukt i modia oversikten.
Java
4
star
68

forenklet-deploy

Oversikt over endringer i et team sine applikasjoner
TypeScript
4
star
69

mulighetsrommet

Kotlin
4
star
70

familie-ba-sak-frontend

Saksbehandlerapplikasjon for barnetrygd
TypeScript
4
star
71

autoforward

Simpel app for automagisk forwarding av ingresser til kubernetes cluster
Rust
4
star
72

personopplysninger

Vising av personopplysninger i henhold til GDPR
TypeScript
4
star
73

ntnu-process-mining

Jupyter Notebook
4
star
74

eux-rina-irsync

EESSI RINA IR SYNC app
Java
4
star
75

pam-import-api

import api for vacancies
Kotlin
4
star
76

amplitude-data-wrapper

python wrapper for the amplitude analytics and taxonomy APIs
Python
4
star
77

fpfordel

Java
4
star
78

sykepengesoknad-frontend

TypeScript
4
star
79

nginx-oidc-docker

Docker image to serve single page applications with open id connect auth and proxy settings.
JavaScript
4
star
80

syfoinntektsmelding

Mottak og håndtering av inntektsmeldinger
Kotlin
4
star
81

amt-arena-acl

Tjeneste som leser data fra Arena, muterer det til AMT-Domene
Kotlin
3
star
82

familie-integrasjoner

Kotlin
3
star
83

farskapsportal-ui

UI for farskapserklæring
TypeScript
3
star
84

helseopplysninger

Backend for helseopplysninger
Kotlin
3
star
85

hm-grunndata-register

Grunndata registrering
Kotlin
3
star
86

pensjon-etterlatte-saksbehandling

Kotlin
3
star
87

dittnav

Forside for tjenester på nav.no som krever innlogging. Viser meldinger, tjenester og varsler tilpasset brukerens status og gruppe på første side
JavaScript
3
star
88

sykepengesoknad-backend

Kotlin
3
star
89

familie-ef-soknad

Søknad for enslig forsørger
TypeScript
3
star
90

ssdx

An app to automate Salesforce DX operations
Python
3
star
91

amt-tiltak

Backend tjeneste for arbeidsmarkedstiltak
Kotlin
3
star
92

boot-cluster-conditionals

Kotlin
3
star
93

fp-felles

Felles kode / bibliotek for foredrepenger området
Java
3
star
94

crm-platform-integration

Kafka integration layer for Salesforce
Apex
3
star
95

familie-felles

Lite fellesbibliotek for familie-ytelsene
Kotlin
3
star
96

leesah-game

Hendelsedrevet applikasjonsutviklingspill!
Kotlin
3
star
97

dvh-airflow-kafka

Python
3
star
98

crm-community-base

Registration handlers and other base components for Salesforce Communities
HTML
3
star
99

eessi-pensjon-saksbehandling-api

Tilby rest endepunkt for eessi pensjon saksbehandling frontend
Kotlin
3
star
100

navkafka-docker-compose

Repository for automated bootstrapping of NAVs kafka environment through docker compose
Dockerfile
3
star