Skip to content

Commit

Permalink
fix gitea token validation by allowing custom validation url and extr…
Browse files Browse the repository at this point in the history
…acting the proper base api url for github cloud, github enterprise and gitea
  • Loading branch information
tuunit committed Sep 12, 2023
1 parent 854401e commit b8a8d77
Show file tree
Hide file tree
Showing 8 changed files with 306 additions and 72 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
## Changes since v7.5.0
- [#2220](https://github.com/oauth2-proxy/oauth2-proxy/pull/2220) Added binary and docker release platforms (@kvanzuijlen)
- [#2221](https://github.com/oauth2-proxy/oauth2-proxy/pull/2221) Backwards compatible fix for wrong environment variable name (OAUTH2_PROXY_GOOGLE_GROUPS) (@kvanzuijlen)
- [#1989](https://github.com/oauth2-proxy/oauth2-proxy/pull/1989) Fix default scope for keycloak-oidc provider
- [#1989](https://github.com/oauth2-proxy/oauth2-proxy/pull/1989) Fix default scope for keycloak-oidc provider (@tuunit)
- [#2217](https://github.com/oauth2-proxy/oauth2-proxy/pull/2217) Upgrade alpine to version 3.18 (@polarctos)
- [#2229](https://github.com/oauth2-proxy/oauth2-proxy/pull/2229) bugfix: default scopes for OIDCProvider based providers
- [#2229](https://github.com/oauth2-proxy/oauth2-proxy/pull/2229) bugfix: default scopes for OIDCProvider based providers (@tuunit)
- [#2194](https://github.com/oauth2-proxy/oauth2-proxy/pull/2194) Fix Gitea token validation (@tuunit)

# V7.5.0

Expand Down
28 changes: 18 additions & 10 deletions contrib/local-environment/Makefile
Original file line number Diff line number Diff line change
@@ -1,34 +1,42 @@
.PHONY: up
up:
docker-compose up -d
docker compose up -d

.PHONY: %
%:
docker-compose $*
docker compose $*

.PHONY: alpha-config-up
alpha-config-up:
docker-compose -f docker-compose.yaml -f docker-compose-alpha-config.yaml up -d
docker compose -f docker-compose.yaml -f docker-compose-alpha-config.yaml up -d

.PHONY: alpha-config-%
alpha-config-%:
docker-compose -f docker-compose.yaml -f docker-compose-alpha-config.yaml $*
docker compose -f docker-compose.yaml -f docker-compose-alpha-config.yaml $*

.PHONY: nginx-up
nginx-up:
docker-compose -f docker-compose.yaml -f docker-compose-nginx.yaml up -d
docker compose -f docker-compose.yaml -f docker-compose-nginx.yaml up -d

.PHONY: nginx-%
nginx-%:
docker-compose -f docker-compose.yaml -f docker-compose-nginx.yaml $*
docker compose -f docker-compose.yaml -f docker-compose-nginx.yaml $*

.PHONY: keycloak-up
keycloak-up:
docker-compose -f docker-compose-keycloak.yaml up -d
docker compose -f docker-compose-keycloak.yaml up -d

.PHONY: keycloak-%
keycloak-%:
docker-compose -f docker-compose-keycloak.yaml $*
docker compose -f docker-compose-keycloak.yaml $*

.PHONY: gitea-up
gitea-up:
docker compose -f docker-compose-gitea.yaml up -d

.PHONY: gitea-%
gitea-%:
docker compose -f docker-compose-gitea.yaml $*

.PHONY: kubernetes-up
kubernetes-up:
Expand All @@ -41,8 +49,8 @@ kubernetes-down:

.PHONY: traefik-up
traefik-up:
docker-compose -f docker-compose.yaml -f docker-compose-traefik.yaml up -d
docker compose -f docker-compose.yaml -f docker-compose-traefik.yaml up -d

.PHONY: traefik-%
traefik-%:
docker-compose -f docker-compose.yaml -f docker-compose-traefik.yaml $*
docker compose -f docker-compose.yaml -f docker-compose-traefik.yaml $*
65 changes: 65 additions & 0 deletions contrib/local-environment/docker-compose-gitea.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# This docker-compose file can be used to bring up an example instance of oauth2-proxy
# for manual testing and exploration of features.
# Alongside OAuth2-Proxy, this file also starts Gitea to act as the identity provider,
# HTTPBin as an example upstream.
#
# This can either be created using docker-compose
# docker-compose -f docker-compose-gitea.yaml <command>
# Or:
# make gitea-<command> (eg. make gitea-up, make gitea-down)
#
# Access http://oauth2-proxy.localtest.me:4180 to initiate a login cycle using user=admin@example.com, password=password
# Access http://gitea.localtest.me:3000 with the same credentials to check out the settings
version: '3.0'
services:
oauth2-proxy:
container_name: oauth2-proxy
image: gitea-oauth #quay.io/oauth2-proxy/oauth2-proxy:v7.4.0
command: --config /oauth2-proxy.cfg
hostname: oauth2-proxy
volumes:
- "./oauth2-proxy-gitea.cfg:/oauth2-proxy.cfg"
restart: unless-stopped
networks:
gitea: {}
httpbin: {}
oauth2-proxy: {}
depends_on:
- httpbin
- gitea
ports:
- 4180:4180/tcp

httpbin:
container_name: httpbin
image: kennethreitz/httpbin:latest
hostname: httpbin
ports:
- 8080:80
networks:
httpbin:
aliases:
- httpbin.localtest.me

gitea:
image: gitea/gitea:latest
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
gitea:
aliases:
- gitea.localtest.me
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"

networks:
httpbin: {}
gitea: {}
oauth2-proxy: {}
19 changes: 19 additions & 0 deletions contrib/local-environment/oauth2-proxy-gitea.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
http_address="0.0.0.0:4180"
cookie_secret="OQINaROshtE9TcZkNAm-5Zs2Pv3xaWytBmc5W7sPX7w="
email_domains=["localhost"]
cookie_secure="false"
upstreams="http://httpbin"
cookie_domains=[".localtest.me"] # Required so cookie can be read on all subdomains.
whitelist_domains=[".localtest.me"] # Required to allow redirection back to original requested target.

client_id="ef0c2b91-2e38-4fa8-908d-067a35dbb71c"
client_secret="gto_qdppomn2p26su5x46tyixj7bcny5m5er2s67xhrponq2qtp66f3a"
redirect_url="http://oauth2-proxy.localtest.me:4180/oauth2/callback"

# gitea provider
provider="github"
provider_display_name="Gitea"
login_url="http://gitea.localtest.me:3000/login/oauth/authorize"
redeem_url="http://gitea.localtest.me:3000/login/oauth/access_token"
validate_url="http://gitea.localtest.me:3000/api/v1/user/emails"

39 changes: 20 additions & 19 deletions docs/docs/configuration/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Valid providers are :
- [ADFS](#adfs-auth-provider)
- [Facebook](#facebook-auth-provider)
- [GitHub](#github-auth-provider)
- [Gitea](#gitea-auth-provider)
- [Keycloak](#keycloak-auth-provider)
- [GitLab](#gitlab-auth-provider)
- [LinkedIn](#linkedin-auth-provider)
Expand All @@ -21,7 +22,6 @@ Valid providers are :
- [Nextcloud](#nextcloud-provider)
- [DigitalOcean](#digitalocean-auth-provider)
- [Bitbucket](#bitbucket-auth-provider)
- [Gitea](#gitea-auth-provider)

The provider can be selected using the `provider` configuration value.

Expand Down Expand Up @@ -177,6 +177,25 @@ If you are using GitHub enterprise, make sure you set the following to the appro
-redeem-url="http(s)://<enterprise github host>/login/oauth/access_token"
-validate-url="http(s)://<enterprise github host>/api/v3"

### Gitea Auth Provider

1. Create a new application: `https://< your gitea host >/user/settings/applications`
2. Under `Redirect URI` enter the correct URL i.e. `https://<proxied host>/oauth2/callback`
3. Note the Client ID and Client Secret.
4. Pass the following options to the proxy:

```
--provider="github"
--redirect-url="https://<proxied host>/oauth2/callback"
--provider-display-name="Gitea"
--client-id="< client_id as generated by Gitea >"
--client-secret="< client_secret as generated by Gitea >"
--login-url="https://< your gitea host >/login/oauth/authorize"
--redeem-url="https://< your gitea host >/login/oauth/access_token"
--validate-url="https://< your gitea host >/api/v1/user/emails"
```


### Keycloak Auth Provider

:::note
Expand Down Expand Up @@ -660,24 +679,6 @@ To use the provider, pass the following options:
The default configuration allows everyone with Bitbucket account to authenticate. To restrict the access to the team members use additional configuration option: `--bitbucket-team=<Team name>`. To restrict the access to only these users who has access to one selected repository use `--bitbucket-repository=<Repository name>`.
### Gitea Auth Provider
1. Create a new application: `https://< your gitea host >/user/settings/applications`
2. Under `Redirect URI` enter the correct URL i.e. `https://<proxied host>/oauth2/callback`
3. Note the Client ID and Client Secret.
4. Pass the following options to the proxy:
```
--provider="github"
--redirect-url="https://<proxied host>/oauth2/callback"
--provider-display-name="Gitea"
--client-id="< client_id as generated by Gitea >"
--client-secret="< client_secret as generated by Gitea >"
--login-url="https://< your gitea host >/login/oauth/authorize"
--redeem-url="https://< your gitea host >/login/oauth/access_token"
--validate-url="https://< your gitea host >/api/v1"
```
## Email Authentication
Expand Down
98 changes: 98 additions & 0 deletions providers/gitea_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package providers

import (
"context"
"net/http"
"net/http/httptest"
"net/url"
"testing"

"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
"github.com/stretchr/testify/assert"
)

func testGiteaProvider(hostname string, opts options.GitHubOptions) *GitHubProvider {
p := NewGitHubProvider(
&ProviderData{
ProviderName: "Gitea",
LoginURL: &url.URL{},
RedeemURL: &url.URL{},
ProfileURL: &url.URL{},
ValidateURL: &url.URL{Path: "/api/v1/user/emails"},
Scope: ""},
opts)
p.ProviderName = "Gitea"

if hostname != "" {
updateURL(p.Data().LoginURL, hostname)
updateURL(p.Data().RedeemURL, hostname)
updateURL(p.Data().ProfileURL, hostname)
updateURL(p.Data().ValidateURL, hostname)
}
return p
}

func testGiteaBackend(payloads map[string][]string) *httptest.Server {
pathToQueryMap := map[string][]string{
"/api/v1/repos/oauth2-proxy/oauth2-proxy": {""},
"/api/v1/repos/oauth2-proxy/oauth2-proxy/collaborators/mbland": {""},
"/api/v1/user": {""},
"/api/v1/user/emails": {""},
"/api/v1/user/orgs": {"page=1&per_page=100", "page=2&per_page=100", "page=3&per_page=100"},
}

return httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
query, ok := pathToQueryMap[r.URL.Path]
validQuery := false
index := 0
for i, q := range query {
if q == r.URL.RawQuery {
validQuery = true
index = i
}
}
payload := []string{}
if ok && validQuery {
payload, ok = payloads[r.URL.Path]
}
if !ok {
w.WriteHeader(404)
} else if !validQuery {
w.WriteHeader(404)
} else if payload[index] == "" {
w.WriteHeader(204)
} else {
w.WriteHeader(200)
w.Write([]byte(payload[index]))
}
}))
}

func TestGiteaProvider_ValidateSessionWithBaseUrl(t *testing.T) {
b := testGiteaBackend(map[string][]string{})
defer b.Close()

bURL, _ := url.Parse(b.URL)
p := testGiteaProvider(bURL.Host, options.GitHubOptions{})

session := CreateAuthorizedSession()

valid := p.ValidateSession(context.Background(), session)
assert.False(t, valid)
}

func TestGiteaProvider_ValidateSessionWithUserEmails(t *testing.T) {
b := testGiteaBackend(map[string][]string{
"/api/v1/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
})
defer b.Close()

bURL, _ := url.Parse(b.URL)
p := testGiteaProvider(bURL.Host, options.GitHubOptions{})

session := CreateAuthorizedSession()

valid := p.ValidateSession(context.Background(), session)
assert.True(t, valid)
}
Loading

0 comments on commit b8a8d77

Please sign in to comment.