api/internal/filter/oidc.go (68 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package filter import ( "net/http" "github.com/coreos/go-oidc/v3/oidc" "github.com/gin-gonic/gin" "golang.org/x/oauth2" "github.com/apisix/manager-api/internal/conf" "github.com/apisix/manager-api/internal/log" ) type Token struct { AccessToken string } func (token *Token) Token() (*oauth2.Token, error) { oauth2Token := &oauth2.Token{AccessToken: token.AccessToken} return oauth2Token, nil } func Oidc() gin.HandlerFunc { return func(c *gin.Context) { if c.Request.URL.Path == "/apisix/admin/oidc/login" { url := conf.OidcConfig.AuthCodeURL(conf.State) c.Redirect(302, url) c.Abort() return } if c.Request.URL.Path == "/apisix/admin/oidc/callback" { state := c.Query("state") if state != conf.State { log.Warn("the state does not match") c.AbortWithStatus(http.StatusForbidden) return } // in exchange for token oauth2Token, err := conf.OidcConfig.Exchange(c, c.Query("code")) if err != nil { log.Warnf("exchange code for token failed: %s", err) c.AbortWithStatus(http.StatusForbidden) return } // in exchange for user's information token := &Token{oauth2Token.AccessToken} providerConfig := oidc.ProviderConfig{UserInfoURL: conf.OidcUserInfoURL} provider := providerConfig.NewProvider(c) userInfo, err := provider.UserInfo(c, token) if err != nil { log.Warnf("exchange access_token for user's information failed: %s", err) c.AbortWithStatus(http.StatusForbidden) return } // set the cookie conf.CookieStore.MaxAge(conf.OidcExpireTime) cookie, _ := conf.CookieStore.Get(c.Request, "oidc") cookie.Values["oidc_id"] = userInfo.Subject conf.OidcId = userInfo.Subject cookie.Save(c.Request, c.Writer) c.AbortWithStatus(http.StatusOK) return } if c.Request.URL.Path == "/apisix/admin/oidc/logout" { cookie, _ := conf.CookieStore.Get(c.Request, "oidc") if cookie.IsNew { c.AbortWithStatus(http.StatusForbidden) return } cookie.Options.MaxAge = -1 cookie.Save(c.Request, c.Writer) c.AbortWithStatus(http.StatusOK) return } c.Next() } }