Skip to content

Conversation

@Elektordi
Copy link
Contributor

@Elektordi Elektordi commented Nov 29, 2022

The keycloak_oidc provider uses the access_token instead of the id_token.

Description

I had 500 errors when using keycloak_oidc provider out of the box, and logs where indicating a problem with the audience:

[oauthproxy.go:830] Error creating session during OAuth2 callback: audience claims [aud] do not exist in claims: [...]

Motivation and Context

oauth2-proxy relies on the audience "aud" field, and the officiel keycloak documentation states that the access_token is not design to hold the audience of the client requesting the token:

https://www.keycloak.org/docs/latest/server_admin/#_audience_resolve

The frontend client itself is not automatically added to the access token audience, therefore allowing easy differentiation between the access token and the ID token, since the access token will not contain the client for which the token is issued as an audience.

It is the id_token which is designed for this, and this token is for the OIDC protocol. (where the access_token is for OAuth2 protocol)

It was also confirmed by Keycloak devs on their mailing list some time ago: https://lists.jboss.org/pipermail/keycloak-user/2019-August/018924.html

How Has This Been Tested?

It has been tested with a brand now keycloak and oauth2-proxy, both deployed with docker, and using traefik/whoami as a backend.
Command line: docker run --rm --name oauth2proxy -p 4180:4180 oauth2-proxy --provider=keycloak-oidc --oidc-issuer-url=http://172.17.0.1:8080/realms/test --email-domain=* --upstream=http://172.17.0.1:49156/ --reverse-proxy --http-address=0.0.0.0:4180 --client-id=dev-localhost --client-secret=xxxxxxxxxxxx --cookie-secret=xxxxxxxxxxxxxxxx --redirect-url=http://localhost:4180/oauth2/callback --skip-jwt-bearer-tokens --insecure-oidc-allow-unverified-email

It was tested with both web access, and bearer api access.

Before change: HTTP 500 error on auth2-proxy

After change : No problem.

Checklist:

  • My change requires a change to the documentation or CHANGELOG.
  • I have updated the documentation/CHANGELOG accordingly.
  • I have created a feature (non-master) branch for my PR.

(I'm not sure if I need to update "Breaking Changes" in CHANGELOG, because it may break installations where people have customized their KC to add specific stuff to their access_token, even is the specs says you should not)

@Elektordi Elektordi requested a review from a team as a code owner November 29, 2022 14:16
Elektordi added a commit to Elektordi/oauth2-proxy that referenced this pull request Nov 29, 2022
@JoelSpeed
Copy link
Member

Have you looked at the history of this provider? Is it possible the behaviour has changed in keycloak and your change makes it supported for newer versions but breaks older versions?
Would be good to get reviews and acks from some other keycloak folk before we merge.

If you can get a keycloak maintainer to comment that would help as well

@Elektordi
Copy link
Contributor Author

Elektordi commented Dec 29, 2022

One of the devs from redhat already confirmed this:
https://lists.jboss.org/pipermail/keycloak-user/2019-August/018924.html
I'll check for changes about this in history of the file..

Furthermore, access_token is from Oauth2 spec (and used in keycloak provider), and id_token is from oidc spec.

@github-actions
Copy link
Contributor

This pull request has been inactive for 60 days. If the pull request is still relevant please comment to re-activate the pull request. If no action is taken within 7 days, the pull request will be marked closed.

@github-actions github-actions bot added the Stale label Feb 28, 2023
@babs
Copy link
Contributor

babs commented Feb 28, 2023

IMHO, this is still relevant.

@JoelSpeed JoelSpeed removed the Stale label Feb 28, 2023
@JoelSpeed
Copy link
Member

This sounds like something we should fix, but I'm wondering if there's a way to avoid a breaking change here, any thoughts?

@babs
Copy link
Contributor

babs commented Apr 22, 2023

I'm not quite sure what it could break as the later adds aud claims defacto among other things if I remember correctly.
If users want to use the access token, the proper provider to use is the non oidc flavor of keycloak ;)

@yann-soubeyrand
Copy link

yann-soubeyrand commented May 2, 2023

Hello, I’ve asked Keycloak developers for some clarification:
keycloak/keycloak#20033

@babs
Copy link
Contributor

babs commented May 29, 2023

As stated by @Elektordi ,

access_token is from Oauth2 spec (and used in keycloak provider), and id_token is from oidc spec.

If you want to use access_token you can use the keycloak provider, and leave keycloak-oidc for .... oidc and therefore use the proper token :)

@github-actions
Copy link
Contributor

This pull request has been inactive for 60 days. If the pull request is still relevant please comment to re-activate the pull request. If no action is taken within 7 days, the pull request will be marked closed.

@github-actions github-actions bot added the Stale label Jul 31, 2023
@babs
Copy link
Contributor

babs commented Jul 31, 2023

Still relevant

@github-actions github-actions bot removed the Stale label Aug 1, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Oct 1, 2023

This pull request has been inactive for 60 days. If the pull request is still relevant please comment to re-activate the pull request. If no action is taken within 7 days, the pull request will be marked closed.

@github-actions github-actions bot added the Stale label Oct 1, 2023
@yann-soubeyrand
Copy link

As stated by @Elektordi ,

access_token is from Oauth2 spec (and used in keycloak provider), and id_token is from oidc spec.

Yes, I know what Oauth2 and OIDC are (technically OIDC is based on Oauth2, so the access token is also and OIDC thing, but I won’t nitpick on this).

If you want to use access_token you can use the keycloak provider, and leave keycloak-oidc for .... oidc and therefore use the proper token :)

Well, if you want pure OIDC, I guess you can just use the OpenID Connect provider. I’m sure you’re aware that the Keycloak provider is already making use of the access token to get the roles and put them in the group list 😉

func (p *KeycloakOIDCProvider) getAccessClaims(ctx context.Context, s *sessions.SessionState) (*accessClaims, error) {
// HACK: This isn't an ID Token, but has similar structure & signing
token, err := p.Verifier.Verify(ctx, s.AccessToken)
if err != nil {
return nil, err
}
var claims *accessClaims
if err = token.Claims(&claims); err != nil {
return nil, err
}
return claims, nil
}

func getClientRoles(claims *accessClaims) []string {
var clientRoles []string
for clientName, access := range claims.ResourceAccess {
accessMap, ok := access.(map[string]interface{})
if !ok {
continue
}
var roles interface{}
if roles, ok = accessMap["roles"]; !ok {
continue
}
for _, role := range roles.([]interface{}) {
clientRoles = append(clientRoles, fmt.Sprintf("%s:%s", clientName, role))
}
}
return clientRoles
}

@github-actions github-actions bot removed the Stale label Oct 4, 2023
@babs
Copy link
Contributor

babs commented Oct 4, 2023

If you want to use access_token you can use the keycloak provider, and leave keycloak-oidc for .... oidc and therefore use the proper token :)

Well, if you want pure OIDC, I guess you can just use the OpenID Connect provider. I’m sure you’re aware that the Keycloak provider is already making use of the access token to get the roles and put them in the group list 😉

@yann-soubeyrand yes, I know, but in this case the aud is missing or wrong, so an extra config has to be made on KC side to make it work comply with OIDC (that, I can't emphase enought, shouldn't have to be done if proper token was used), all that because oauth2-proxy doesn't use the proper token due to legacy KC issue and a global misunderstanding.

I'd also argue: why having 2 code bases to talk to keycloak using the exact same token while the very purpose of keycloak-oidc should be to be defacto compliant with the specs.
It's not like we are talking about removing functionality here, IMHO, it's more fixing a legacy misuse and/or misunderstanding and making things right.

@yann-soubeyrand
Copy link

The problem is that, by default in Keycloak, no ID token claim contains the roles. So it seems there’s no way to avoid user configuration and to exclusively use the ID token. That’s why I asked on Keycloak discussions an advice on the way to go, but I got no answer so far.

@Elektordi
Copy link
Contributor Author

Elektordi commented Oct 5, 2023

no ID token claim contains the roles

I agree, but roles is a more specific feature, and not a needed one (you can use OIDC without roles).

why having 2 code bases to talk to keycloak using the exact same token while the very purpose of keycloak-oidc should be to be defacto compliant with the specs.

That is what I was thinking, the keycloak provider should use access token, and keycloak-oidc the id token, and things would work out of the box (without roles, indeed).

And, btw, multiple people have opened issues because of this bug.
For example, last one I found: #2117

@yann-soubeyrand
Copy link

OK, but then what’s the added value of the Keycloak OIDC provider compared to the generic OIDC provider?

@babs
Copy link
Contributor

babs commented Oct 5, 2023

good question, initially probably not that much, now there is another pull request for backend logout for example

@github-actions
Copy link
Contributor

github-actions bot commented Dec 5, 2023

This pull request has been inactive for 60 days. If the pull request is still relevant please comment to re-activate the pull request. If no action is taken within 7 days, the pull request will be marked closed.

@github-actions github-actions bot added the Stale label Dec 5, 2023
@babs
Copy link
Contributor

babs commented Dec 6, 2023

Not stalled!

@olivierlambert
Copy link

olivierlambert commented Jul 9, 2024

I had this temporary "fix" in Keycloak for a while (using Mappers), and now with Keycloak 25.1, I can't make it work anymore for any new client I add (or if I modify a previous client):

[oauthproxy.go:888] Error creating session during OAuth2 callback: audience from claim aud with value [xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx account] does not match with any of allowed audiences map[elastic:{}]

I checked 10 times, follow the doc in the exact same details and despite that, I can't make it work anymore. Note there's extra fields/boxes in Keycloak 25, that could made the configuration different:
image

Does anyone with a recent Keycloak made it work?

That would be great to get it solved via this PR, so we do not need any extra config anymore

@PaddyKe
Copy link

PaddyKe commented Jul 28, 2024

Does anyone with a recent Keycloak made it work?

That would be great to get it solved via this PR, so we do not need any extra config anymore

I just ran into the same issue. For some reason, Keycloak 25 seems to add some kind of GUID into the aud scope instead of the actual client id.
I was able to make it work by not specifying any value in the "Include Client Audience" and instead manually entering the client id in "Include Custom Audience" field.

image

@babs
Copy link
Contributor

babs commented Jul 29, 2024

@Elektordi @JoelSpeed @kvanzuijlen little up ?

@Fmstrat
Copy link

Fmstrat commented Aug 4, 2024

Could someone provide a how-to for the workaround?

@JoniJnm
Copy link

JoniJnm commented Sep 17, 2024

I "fixed" it using oidc_extra_audiences with a fixed value. Maybe aud or account, check the property aud in your jwt token

oidc_extra_audiences = [ "account" ]

@babs
Copy link
Contributor

babs commented Sep 18, 2024

@JoelSpeed ?

@franco-viotti
Copy link

@PaddyKe solution worked for me, thanks! I'm using Keycloak 25.0.1 and oauth2-proxy 7.6.0

jakubgs added a commit to status-im/infra-role-oauth-proxy that referenced this pull request Nov 28, 2024
It is a known issue with Keycloak:
oauth2-proxy/oauth2-proxy#1913
oauth2-proxy/oauth2-proxy#1916

Signed-off-by: Jakub Sokołowski <jakub@status.im>
@tuunit
Copy link
Member

tuunit commented Apr 27, 2025

Hey guys,

as this has been open for years now and I fully agree with @babs on the following:

I'd also argue: why having 2 code bases to talk to keycloak using the exact same token while the very purpose of keycloak-oidc should be to be defacto compliant with the specs.
It's not like we are talking about removing functionality here, IMHO, it's more fixing a legacy misuse and/or misunderstanding and making things right.

I investigated this whole mess in-depth!

First of all, I want to get some confusion out of the way.

OK, but then what’s the added value of the Keycloak OIDC provider compared to the generic OIDC provider?

TLDR; The Keycloak provider is deprecated and the KeycloakOIDC provider extends the generic OIDC provider and therefore offers all generic OIDC options and on top the extraction of roles from Keycloaks access token.

A couple years ago, Nick and Joel started working on generalising the code base. One of the goals was and still is, to try to have at little as possible specific provider code as possible, for this reason the generic OIDC provider was introduced and in the long run all OIDC compliant providers should only extend its functionality. The Keycloak provider was kept to stay backwards compatible and not break existing users setup. We now highlight in the docs and in the provider code that the normal Keycloak provider is therefore deprecated and people should use the KeycloakOIDC provider.

Main point which this PR was supposed to address:

Standard Compliance
Align with the OIDC specification, where the ID token is meant for authentication (containing user identity claims) and Access tokens are for authorization (OAuth2) and aren't guaranteed to contain the expected aud claim.

Breaking change
As already identified, the code was build under the assumption that the access token is used for extracting the roles:

type realmAccess struct {
Roles []string `json:"roles"`
}
type accessClaims struct {
RealmAccess realmAccess `json:"realm_access"`
ResourceAccess map[string]interface{} `json:"resource_access"`
}

func (p *KeycloakOIDCProvider) extractRoles(ctx context.Context, s *sessions.SessionState) error {
claims, err := p.getAccessClaims(ctx, s)
if err != nil {
return err
}
var roles []string
roles = append(roles, claims.RealmAccess.Roles...)
roles = append(roles, getClientRoles(claims)...)
// Add to groups list with `role:` prefix to distinguish from groups
for _, role := range roles {
s.Groups = append(s.Groups, formatRole(role))
}
return nil
}

Those aren't included in the ID Token returned by Keycloak:

ID Token:

{
  "exp": 1745780789,
  "iat": 1745780729,
  "auth_time": 1745780729,
  "jti": "76d39596-4af7-4bf5-8688-72232e064a42",
  "iss": "http://keycloak.localtest.me:9080/realms/oauth2-proxy",
  "aud": "oauth2-proxy",
  "sub": "3356c0a0-d4d5-4436-9c5a-2299c71c08ec",
  "typ": "ID",
  "azp": "oauth2-proxy",
  "sid": "8eb0bed4-de02-46e7-824f-6bb8d476a590",
  "at_hash": "pr_FFqbZrJ4q7SYld2B5Cg",
  "email_verified": true,
  "preferred_username": "admin@example.com",
  "email": "admin@example.com"
}

Access Token:

{                                                                                                                                                                                                                                               
  "exp": 1745780789,                                                                                                                                                                                                                            
  "iat": 1745780729,                                                                                                                                                                                                                            
  "auth_time": 1745780729,                                                                                                                                                                                                                      
  "jti": "af7fb1dd-143e-4d83-80f5-bb4201b2c322",                                                                                                                                                                                                
  "iss": "http://keycloak.localtest.me:9080/realms/oauth2-proxy",                                                                                                                                                                               
  "aud": [                                                                                                                                                                                                                                      
    "oauth2-proxy-realm",                                                                                                                                                                                                                       
    "account"                                                                                                                                                                                                                                   
  ],                                                                                                                                                                                                                                            
  "sub": "3356c0a0-d4d5-4436-9c5a-2299c71c08ec",                                                                                                                                                                                                
  "typ": "Bearer",                                                                                                                                                                                                                              
  "azp": "oauth2-proxy",                                                                                                                                                                                                                        
  "sid": "8eb0bed4-de02-46e7-824f-6bb8d476a590",                                                                                                                                                                                                
  "realm_access": {                                                                                                                                                                                                                             
    "roles": [                                                                                                                                                                                                                                  
      "create-realm",                                                                                                                                                                                                                           
      "offline_access",                                                                                                                                                                                                                         
      "admin",                                                                                                                                                                                                                                  
      "uma_authorization"                                                                                                                                                                       
    ]                                                                                                                                                                                           
  },                                                                                                                                                                                            
  "resource_access": {                                                                                                                                                                          
    "oauth2-proxy-realm": {                                                                                                                                                                     
      "roles": [                                                                                                                                                                                
        "view-realm",                                                                                                                                                                           
        "view-identity-providers",                                                                                                                                                              
        "manage-identity-providers",                                                                                                                                                            
        "impersonation",                                                                                                                                                                        
        "create-client",                                                                                                                                                                        
        "manage-users",                                                                                                                                                                         
        "query-realms",                                                                                                                                                                         
        "view-authorization",                                                                                                                                                                   
        "query-clients",                                                                                                                                                                        
        "query-users",                                                                                                                                                                          
        "manage-events",                                                                                                                                                                        
        "manage-realm",                                                                                                                                                                         
        "view-events",                                                                                                                                                                          
        "view-users",                                                                                                                                                                           
        "view-clients",                                                                                                                                                                         
        "manage-authorization",                                                                                                                                                                 
        "manage-clients",                                                                                                                                                                       
        "query-groups"                                                                                                                                                                          
      ]                                                                                                                                                                                         
    },                                          
    "account": {                                
      "roles": [                                
        "manage-account",                       
        "manage-account-links",                 
        "view-profile"                          
      ]                                         
    }                                           
  },                                            
  "scope": "openid profile email",              
  "email_verified": true,                       
  "preferred_username": "admin@example.com",    
  "email": "admin@example.com"                  
}

Drill down

As keycloak_oidc.go is inheriting the generic functionality from oidc.go the actual session validation and creation is happening here:

func (p *OIDCProvider) createSession(ctx context.Context, token *oauth2.Token, refresh bool) (*sessions.SessionState, error) {
_, err := p.verifyIDToken(ctx, token)
if err != nil {
switch err {
case ErrMissingIDToken:
// IDToken is mandatory in Redeem but optional in Refresh
if !refresh {
return nil, errors.New("token response did not contain an id_token")
}
default:
return nil, fmt.Errorf("could not verify id_token: %v", err)
}
}
rawIDToken := getIDToken(token)
ss, err := p.buildSessionFromClaims(rawIDToken, token.AccessToken)
if err != nil {
return nil, err
}
ss.AccessToken = token.AccessToken
ss.RefreshToken = token.RefreshToken
ss.IDToken = rawIDToken
ss.CreatedAtNow()
ss.SetExpiresOn(token.Expiry)
return ss, nil
}

func (p *OIDCProvider) ValidateSession(ctx context.Context, s *sessions.SessionState) bool {
ctx = oidc.ClientContext(ctx, requests.DefaultHTTPClient)
_, err := p.Verifier.Verify(ctx, s.IDToken)
if err != nil {
logger.Errorf("id_token verification failed: %v", err)
return false
}

And those locations are already properly using the access_token and id_token respectively.
Therefore this PR doesn't actually address the OIDC compliance as it is already in place and properly working.

So what is the problem then?
What this PR actually changed isn't the session creation or the session validation logic but instead it is just fighting a symptom of a strange implementation. In which we abuse the p.Verifier.Verify for parsing the access_token into an token interface. To be able to call the claim extraction method on it.

What really needs to be fixed is how we extract the claims from the access token of Keycloak. Which at the point of usage in getAccessClaims(...) has already been through the exchange and validation.

Therefore I propose we remove the unnecessary verification in:

func (p *KeycloakOIDCProvider) getAccessClaims(ctx context.Context, s *sessions.SessionState) (*accessClaims, error) {
// HACK: This isn't an ID Token, but has similar structure & signing
token, err := p.Verifier.Verify(ctx, s.AccessToken)
if err != nil {
return nil, err
}

and instead fix the actual problem like so:

func (p *KeycloakOIDCProvider) getAccessClaims(ctx context.Context, s *sessions.SessionState) (*accessClaims, error) {
        // extract payload from jwt
        // pseudo code
        // payload := decode(jwtParts[1])
        
	var claims *accessClaims
	if err := json.Unmarshal(payload, claims); err != nil {
		return nil, err
	}
	return claims, nil
}

@Elektordi What you correctly identified, is the fact that the tests did indeed only use the Access Token instead of the ID Token, which was an an oversight and should stay as proposed by your PR. In hindsight, this might be why the assumption was made that the KeycloakOIDC provider is using the access_token instead of the id_token for verification. Which isn't the case for the actual session creation and validation.

CC: @JoelSpeed @Elektordi @babs @yann-soubeyrand

@tuunit tuunit force-pushed the fix-keycloak-oidc branch 2 times, most recently from c729c46 to 05ab7d2 Compare April 27, 2025 21:47
@tuunit
Copy link
Member

tuunit commented Apr 27, 2025

  • I updated the branch, resolved all conflicts
  • Applied my proposed fix
  • Fixed the tests accordingly to reflect the usage of id token and access token
  • Changed the title from "Fix wrong token used in Keycloak OIDC provider" to "fix: role extraction from access token in keycloak oidc"

@tuunit tuunit force-pushed the fix-keycloak-oidc branch 2 times, most recently from 5d6835a to 20eeae5 Compare April 27, 2025 22:17
@tuunit tuunit changed the title Fix wrong token used in Keycloak OIDC provider fix: keycloak oidc role extraction from access token Apr 27, 2025
@tuunit tuunit changed the title fix: keycloak oidc role extraction from access token fix: role extraction from access token in keycloak oidc Apr 27, 2025
tuunit
tuunit previously approved these changes Apr 27, 2025
@JoelSpeed JoelSpeed merged commit 7b41c8e into oauth2-proxy:master Apr 28, 2025
4 checks passed
salmanazmat666 pushed a commit to sensysllc/oauth2-proxy that referenced this pull request Nov 6, 2025
* deps: remove tools/reference-gen from go.mod

Remove github.com/oauth2-proxy/tools/reference-gen from dependencies.
Instead we are now running it with "go run" with a version suffix.

Long version:
- github.com/oauth2-proxy/tools/reference-gen is removed from
  tools/tool/go
- in pkg/apis/options/doc.go we now run reference-run with a version
  suffix (go run package@version) with the version comming from go.mod.
- the "//go:generate" line is split in 2 lines (using the -command
  flag) for readability
- "go mod tidy" for cleaning dependencies from go.mod, go.sum

Note: we are not upgrading reference-gen here. That will be a further
separate change.

* chore(deps): update dependency @easyops-cn/docusaurus-search-local to ^0.49.0

* chore(deps): update gomod (oauth2-proxy#2952)

* chore(deps): update gomod

Co-authored-by: Jan Larwig <jan@larwig.com>

* chore(deps): update module github.com/golang-jwt/jwt/v5 to v5.2.2 [security] (oauth2-proxy#3003)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update golang dependencies and pin to latest golang v1.23.x release (oauth2-proxy#3011)

Signed-off-by: Jan Larwig <jan@larwig.com>

* release v7.8.2 (oauth2-proxy#3012)

* update to release version v7.8.2

* docs: release letter

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* chore(deps): update dependency golangci/golangci-lint to v1.64.8 (oauth2-proxy#3004)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat: update HashNonce to use crypto/sha256 (oauth2-proxy#2967)

Signed-off-by: egibs <20933572+egibs@users.noreply.github.com>

* chore(deps): update docker-compose (oauth2-proxy#3005)

* docs: fix gitlab docs url for oauth2 integration (oauth2-proxy#3002)

* Update gitlab.md with correct url for creating an application

* docs: fix gitlab docs url for oauth2 integration

---------

Co-authored-by: Jan Larwig <jan@larwig.com>

* feat: allow to set non-default authorization request response mode (oauth2-proxy#3001)

* Update Go version in devcontainer

* Add option to change response mode in authorization request

* Fix option name

* Update docs and changelog

* Rename config value to underscore

* Add unit tests for added parameter

* Move change to upcoming release

* Generate alpha config

---------

Co-authored-by: Michael Cornel <michael@stieler.it>

* chore(deps): update docker-compose

* chore(deps): update gitea/gitea docker tag to v1.23.7 (oauth2-proxy#3030)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Add --bearer-token-login-fallback option (oauth2-proxy#2924)

* add --deny-invalid-bearer-tokens

* update changelog

* PR feedback, update api-routes description

* update --api-routes description

* revert load_test fix that I needed locally

---------

Co-authored-by: Justin Ryan <j.ryan@mwam.com>

* chore(deps): update module golang.org/x/net to v0.38.0 [security] (oauth2-proxy#3035)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): upgrade to latest golang v1.23.x release (oauth2-proxy#3041)

* chore(deps): update docker-compose (oauth2-proxy#3038)

* fix(entra-id): use federated credentials for refresh token (oauth2-proxy#3031)

* fix: use federated credentials to refresh token in entra id

* fix: add some error handling

* chore: update changelog

* chore: update comments

* chore: update comments

* doc: reference entra id docs and clearer phrasing of comments

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* chore(deps): update ghcr.io/dexidp/dex docker tag to v2.42.1 (oauth2-proxy#3044)

* doc(entra-id): correct toml field in sample (oauth2-proxy#2946)


---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* chore(build): refactoring makefile for better usability and introducing a default help target (oauth2-proxy#2930)

* fix: role extraction from access token in keycloak oidc  (oauth2-proxy#1916)

* Fix wrong token used in Keycloak OIDC provider

* Update CHANGELOG for PR oauth2-proxy#1916

* Update tests

* fix: keycloak oidc role extraction

---------

Co-authored-by: Jan Larwig <jan@larwig.com>

* feat: ability to parse JWT encoded profile claims (oauth2-proxy#3014)

* fix: parse JWT profile claims

* Comment with OIDC specs reference

* fix: formatting

* Updated changelog

---------

Co-authored-by: Jan Larwig <jan@larwig.com>

* release: v7.9.0 (oauth2-proxy#3047)

* add new docs version 7.9.x

* update to release version v7.9.0

* doc: add changelog summary

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* docs: clear up multiple-providers is unimplemented (oauth2-proxy#3046)

* docs: clear up multiple-providers is unimplemented

Currently this configuration option is held up by oauth2-proxy#926. So users don't
assume this solution will work for them, and later find the feature is
not yet implemented -- own the shortcoming clearly.

* doc: add note about missing multi provider implementation to versioned docs

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* docs: add note about version obfuscation to footer option (oauth2-proxy#3051)

Signed-off-by: Jan Larwig <jan@larwig.com>

* chore(deps): update docker-compose (oauth2-proxy#3074)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): drop golang.org/x/exp/{slices,maps} (oauth2-proxy#3065)

Use Go 1.23 stdlib instead: slices, maps.

* chore(lint): fix staticcheck issues (oauth2-proxy#3061)

* chores: fix staticcheck QF1012

Fix use of fmt.Sprintf when writing to a writer.
https://staticcheck.dev/docs/checks/#QF1012
oauth2-proxy#3060

* chores: fix staticcheck QF1003

Use switch instead of multiple if/else.
https://staticcheck.dev/docs/checks/#QF1003
oauth2-proxy#3060

* chores: exclude staticcheck QF1008 for now

We aim to migrate golangci-lint to v2
Let's disable QF1008 (Omit embedded fields from selector expression)
for now.
https://staticcheck.dev/docs/checks/#QF1008

* chores: fix golangci config: run.deadline -> timeout

Rename config option to match v1 documentation: deadline -> timeout.
https://golangci.github.io/legacy-v1-doc/usage/configuration/#run-configuration

This error has been spotted by golangci-lint v2 migration tool.

* chores: fix staticcheck QF1012

* chores: major upgrade of golangci-lint from v1.64.8 to v2.1.6 (oauth2-proxy#3062)

.golangci.yml migrated with "golangci-lint migrated" and then tweaked to add comments back.

* feat: support for multiple github orgs (oauth2-proxy#3072)

* fix for github teams

* Update github.go

* added errorhandling

* Update github.md

* refactored GitHub provider

refactored hasOrg, hasOrgAndTeams and hasTeam into hasAccess to stay within function limit

* reverted Refactoring

* refactored github.go

- joined hasOrgAndTeamAccess into checkRestrictions

* refactored github.go

- reduced number of returns of function checkRestrictions to 4

* updated GitHub provider to accept legacy team ids

* GoFmt and golangci-lint

Formatted with GoFmt and followed recommendations of GoLint

* added Tests

added Tests for checkRestrictions.

* refactored in maintainer feedback

* Removed code, documentation and tests for legacy ids

* add changelog and update docs

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* Create FUNDING.yml

* feat: bump to go1.24.5 and full dependency update (oauth2-proxy#3116)

* upgrade to go1.24.5

dependency updates

lint fixes

chore(deps): upgrade github.com/spf13/viper to v1.20.1

Note that this upgrade also implied to upgrade github.com/mitchellh/mapstructure
(nowadays unmaintained: https://gist.github.com/mitchellh/90029601268e59a29e64e55bab1c5bdc)
to github.com/go-viper/mapstructure/v2.

fix: adapt tests to match mapstructure v2 error messages

pkg/apis/options/load_test.go: skip tests on Go 1.23

Add a compile guard for Go < 1.24 for the pkg/apis/options/load_test.go
because the LoadYAML test depends on error messages produced by
encoding/json that changed slightly (names of embedded structs are now
reported). As we updated the test for go1.24, the test now fails on
1.23, but just for a slight difference, so we disable the test there.

fix: adapt tests to match mapstructure v2 error messages

remove pre 1.24 disclaimer

add changelog entry

Signed-off-by: Jan Larwig <jan@larwig.com>

Co-Authored-By: Olivier Mengué <dolmen@cpan.org>

* add exclusion for 'avoid meaningless package names' in .golangci.yml

* chore(dep): upgrade all dependencies

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Olivier Mengué <dolmen@cpan.org>
Co-authored-by: Jan Larwig <jan@larwig.com>

* chore(deps): update dependency golangci/golangci-lint to v2.2.2 (oauth2-proxy#3111)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update dependency @easyops-cn/docusaurus-search-local to ^0.51.0 (oauth2-proxy#3098)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update example docker-compose files (oauth2-proxy#3096)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update helm examples (oauth2-proxy#2951)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update alpine base image to v3.22.0 (oauth2-proxy#3097)

* chore(deps): update alpine docker tag to v3.22.0

* add changelog entry

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* fix: return error for empty Redis URL list (oauth2-proxy#3101)

* fix: return error for empty Redis URL list

* add changelog entry

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* add new docs version 7.10.x

* update to release version v7.10.0

* add changelog entry

Signed-off-by: Jan Larwig <jan@larwig.com>

* chore(deps): update dependency @easyops-cn/docusaurus-search-local to ^0.52.0 (oauth2-proxy#3131)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update gomod (oauth2-proxy#3132)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update helm release oauth2-proxy to v7.14.1 (oauth2-proxy#3133)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update docker-compose (oauth2-proxy#3130)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update alpine docker tag to v3.22.1 (oauth2-proxy#3129)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat(cookie) csrf per request limit (oauth2-proxy#3134)

* Allow setting maximum number of csrf cookies, deleting the oldest if necessary

* Add a test for multiple CSRF cookies to remove the old cookie

* Add docs/changelog

* If limit is <=0 do not clear

Signed-off-by: test <bert@transtrend.com>

* Better docs

Co-authored-by: Jan Larwig <jan@larwig.com>

* direct check of option value

Co-authored-by: Jan Larwig <jan@larwig.com>

* direct use of option value

Co-authored-by: Jan Larwig <jan@larwig.com>

* sort based on clock compare vs time compare

Co-authored-by: Jan Larwig <jan@larwig.com>

* clock.Clock does not implement Compare, fix csrf cookie extraction after rename

Signed-off-by: Bert Helderman <bert@transtrend.com>

* Linter fix

* add method signature documentation and slight formatting

Signed-off-by: Jan Larwig <jan@larwig.com>

* fix: test case for csrf cookie limit and flag

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Bert Helderman <bert@transtrend.com>
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: test <bert@transtrend.com>
Co-authored-by: bh-tt <71650427+bh-tt@users.noreply.github.com>

* fix: show login page on broken session cookie (oauth2-proxy#2605)

* fix: redirect on invalid cookie

* docs: update changelog

* chore: remove duplicated code

* fix: status code handling if wrong http method is used

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* Fix local-environment ports (oauth2-proxy#3136)

* Change Dex port in local-environment from 4190 to 5556

Port 4190 is blocked by standards-compliant browsers (e.g. Firefox), as per https://fetch.spec.whatwg.org/#port-blocking.
Port 5556 is used by Dex in its example config files: https://github.com/dexidp/dex/blob/745e1114f341e849f3b0edde45b39c14017deaf8/examples/config-dev.yaml#L50

* Fix upstream in local-environment/oauth2-proxy.cfg

http://httpbin.localtest.me:8080 is only exposed to the host, not to httpbin Docker network.
Causes Bad Gateway before.

* Do not expose unauthenticated httpbin service in local-environment

This defeats the point of having oauth2-proxy.
It has already been misleading by causing the bug fixed in cafc6af.
It serves as a bad example: users might accidentally expose the service they're trying to protect in the first place.

* Remove unnecessary httpbin.localtest.me alias from local-environment

* feat: allow use more possible google admin-sdk api scopes (oauth2-proxy#2743)

* feat: Allow use more possible google admin-sdk api scopes.

* reduce cognitive complexity

Signed-off-by: Bob Du <i@bobdu.cc>

* remove unnecessary else block / indentation

Signed-off-by: Jan Larwig <jan@larwig.com>

* add changelog entry

Signed-off-by: Jan Larwig <jan@larwig.com>

* slight formatting and error message rephrasing

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Bob Du <i@bobdu.cc>
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* feat: add SourceHut (sr.ht) provider (oauth2-proxy#2359)

* Add SourceHut (sr.ht) provider

* fix changelog entry

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* fix: regex substitution for $ signs in upstream path handling before running envsubst (oauth2-proxy#2524)

* Perform a regex replace of $NUM to $$NUM before running envsubst

* Perform a regex replace of $NUM to $$NUM before running envsubst

* add test case; fix linter warnings; add method documentation

Signed-off-by: Jan Larwig <jan@larwig.com>

* add changelog entry

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* feat(cookie): add feature support for cookie-secret-file (oauth2-proxy#3104)

* feat: add feature support for cookie-secret-file

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-Authored-By: Sandy Chen <Yuxuan.Chen@morganstanley.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* feat: use non-default authorization request response mode in OIDC providers (oauth2-proxy#3055)

* fix: OIDC sets response mode

* Update CHANGELOG

* feat: make google-groups argument optional (oauth2-proxy#3138)

add test cases

update documentation

refactor code and some cleanup

update changelog

Signed-off-by: Jan Larwig <jan@larwig.com>

* feat: differentiate between "no available key" and error for redis sessions (oauth2-proxy#3093)

* add some better error handling

* add changelog entry

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* Merge commit from fork

Signed-off-by: Jan Larwig <jan@larwig.com>

* release v7.11.0 (oauth2-proxy#3145)

* add new docs version 7.11.x

* update to release version v7.11.0

* add changelog entry for v7.11.0

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* fix: port for local-environment (oauth2-proxy#3148)

* feat(e2e): add workflow to trigger e2e test suite through PR comments (oauth2-proxy#3153)

* feat(e2e): add workflow to trigger e2e test suite through PR comments

* add empty line

* feat: add Cidaas provider (oauth2-proxy#2273)

* Add sensible logging flag to default setup for logger

* Fix default value flag for sensitive logging

* Remove sensitive logging changes

* Add Cidaas provider

* Update CHANGELOG.md

* Add required groups scope to defaults

* Fix tests

* Remove if block with protected resource

* Fix linting

* Adjust provider sorting, fixes

* Directly handle error return

Co-authored-by: Jan Larwig <jan@larwig.com>

* Use less deep nesting

Co-authored-by: Jan Larwig <jan@larwig.com>

* Directly handle returned error

Co-authored-by: Jan Larwig <jan@larwig.com>

* Pass provider options to Cidaas provider

Co-authored-by: Jan Larwig <jan@larwig.com>

* Add import for provider options

* Fix tests

* Fix linting

* Add Cidaas doc page

* Add Cidaas provider doc page to overview

* Fix link in docs

* Fix link in docs

* Add link to Cidaas

* fix provider order in docs and changelog position

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Teko012 <112829523+Teko012@users.noreply.github.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Kevin Kreitner <kevinkreitner@gmail.com>

* chore(dep): upgrade to latest golang 1.24.6 (oauth2-proxy#3166)

Signed-off-by: Jan Larwig <jan@larwig.com>

* chore(deps): update actions/checkout action to v5 (oauth2-proxy#3164)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update dependency golangci/golangci-lint to v2.4.0 (oauth2-proxy#3161)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update docker-compose (oauth2-proxy#3160)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat: allow disable-keep-alives configuration in upstream (oauth2-proxy#3156)

Signed-off-by: Jan Larwig <jan@larwig.com>

* fix: Gitea team membership (oauth2-proxy#3150)

* bugfix: Gitaa team membership

Gitea doesn't properly fill in all the fields like GitHub,
so implement a series of fallbacks.

Signed-off-by: magic_rb <magic_rb@redalder.org>

* add changelog, documentation and fix groups list

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: magic_rb <magic_rb@redalder.org>
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>

* add new docs version 7.12.x

Signed-off-by: Jan Larwig <jan@larwig.com>

* update to release version v7.12.0

* add changelog entry for v7.12.0

Signed-off-by: Jan Larwig <jan@larwig.com>

* doc: SourceHut documentation fixes (oauth2-proxy#3170)

* fix: SourceHut documentation

- Add it to sidebar and provider index
- Fix broken link

This fixes an oversight in oauth2-proxy#2359, where I had not fully understood how
the documentation works.

Signed-off-by: Conrad Hoffmann <ch@bitfehler.net>

* fix: doc build instructions in docs/README.md

---------

Signed-off-by: Conrad Hoffmann <ch@bitfehler.net>

* chore(deps): update actions/upload-pages-artifact action to v4 (oauth2-proxy#3194)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* doc: update contribution guide to avoid a specific mention of the version of Go being used. (oauth2-proxy#3157)

* fix(deps): revert actions/upload-pages-artifact action to v3 (oauth2-proxy#3211)

Signed-off-by: Richard Ahlquist <richard.jimmy.johansson@gmail.com>

* chore(deps): update alpine docker tag to v3.22.2 (oauth2-proxy#3241)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update actions/setup-node action to v6 (oauth2-proxy#3242)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update actions/stale action to v10 (oauth2-proxy#3193)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update actions/setup-go action to v6 (oauth2-proxy#3191)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update actions/labeler action to v6 (oauth2-proxy#3190)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update helmv3 (oauth2-proxy#3189)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update docker-compose (oauth2-proxy#3188)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update dependency golangci/golangci-lint to v2.5.0 (oauth2-proxy#3212)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore: CI-1455 remove comments

* chore: CI-1455 update docs/configs/alpha-configs.yaml after generate

* fix: CI-1455 lint

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Signed-off-by: egibs <20933572+egibs@users.noreply.github.com>
Signed-off-by: Bert Helderman <bert@transtrend.com>
Signed-off-by: Bob Du <i@bobdu.cc>
Signed-off-by: magic_rb <magic_rb@redalder.org>
Signed-off-by: Conrad Hoffmann <ch@bitfehler.net>
Signed-off-by: Richard Ahlquist <richard.jimmy.johansson@gmail.com>
Co-authored-by: Olivier Mengué <dolmen@cpan.org>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Evan Gibler <20933572+egibs@users.noreply.github.com>
Co-authored-by: Copolycube <kaourintin+github@gmail.com>
Co-authored-by: Michael Cornel <michael@stieler.it>
Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
Co-authored-by: Justin Ryan <jryan@verticalresponse.com>
Co-authored-by: Justin Ryan <j.ryan@mwam.com>
Co-authored-by: Enrico <enrico.pelizzon@gmail.com>
Co-authored-by: Richard Hagen <richard.hagen@gmail.com>
Co-authored-by: Michael Niksa <miniksa@microsoft.com>
Co-authored-by: Guillaume "Elektordi" Genty <github@elektordi.net>
Co-authored-by: ikarius <fred@ikarius.com>
Co-authored-by: Evan Carroll <me@evancarroll.com>
Co-authored-by: Daniel Mersch <94058351+daniel-mersch@users.noreply.github.com>
Co-authored-by: Edward Viaene <ward.viaene@gmail.com>
Co-authored-by: Daniel Givens <1581675+dgivens@users.noreply.github.com>
Co-authored-by: test <bert@transtrend.com>
Co-authored-by: bh-tt <71650427+bh-tt@users.noreply.github.com>
Co-authored-by: Johann <76482511+Primexz@users.noreply.github.com>
Co-authored-by: Simmo Saan <simmo.saan@gmail.com>
Co-authored-by: Bob Du <i@bobdu.cc>
Co-authored-by: Conrad Hoffmann <1226676+bitfehler@users.noreply.github.com>
Co-authored-by: Ashkan Daie <1415513+dashkan@users.noreply.github.com>
Co-authored-by: Sandy Chen <sandy19890604@gmail.com>
Co-authored-by: Sandy Chen <Yuxuan.Chen@morganstanley.com>
Co-authored-by: Sourav Agrawal <146818014+sourava01@users.noreply.github.com>
Co-authored-by: nobletrout <nobletrout@gmail.com>
Co-authored-by: Theron Boerner <hunterboerner@gmail.com>
Co-authored-by: Kevin Kreitner <kevin.kreitner@real-digital.de>
Co-authored-by: Teko012 <112829523+Teko012@users.noreply.github.com>
Co-authored-by: Kevin Kreitner <kevinkreitner@gmail.com>
Co-authored-by: jet <71936688+jet-go@users.noreply.github.com>
Co-authored-by: Richard Brežák <richard@brezak.sk>
Co-authored-by: David Symonds <dsymonds@gmail.com>
Co-authored-by: Richard Ahlquist <richard.jimmy.johansson@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.