Skip to content
Snippets Groups Projects
Commit 1803dc87 authored by Rohith's avatar Rohith
Browse files

- fixing up the logout (#61)

- note, this will probably only work with keycloak
parent 5722def8
No related branches found
No related tags found
No related merge requests found
...@@ -462,10 +462,6 @@ func getOptions() []cli.Flag { ...@@ -462,10 +462,6 @@ func getOptions() []cli.Flag {
Name: "skip-token-verification", Name: "skip-token-verification",
Usage: "TESTING ONLY; bypass's token verification, expiration and roles enforced", Usage: "TESTING ONLY; bypass's token verification, expiration and roles enforced",
}, },
cli.BoolFlag{
Name: "offline-session",
Usage: "enables the offline session of tokens via offline access (defaults false)",
},
cli.BoolTFlag{ cli.BoolTFlag{
Name: "json-logging", Name: "json-logging",
Usage: "switch on json logging rather than text (defaults true)", Usage: "switch on json logging rather than text (defaults true)",
......
...@@ -16,6 +16,7 @@ limitations under the License. ...@@ -16,6 +16,7 @@ limitations under the License.
package main package main
import ( import (
"bytes"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
...@@ -248,43 +249,41 @@ func (r oauthProxy) logoutHandler(cx *gin.Context) { ...@@ -248,43 +249,41 @@ func (r oauthProxy) logoutHandler(cx *gin.Context) {
cx.AbortWithStatus(http.StatusBadRequest) cx.AbortWithStatus(http.StatusBadRequest)
return return
} }
// step: delete the access token // step: can either use the id token or the refresh token
r.clearAccessTokenCookie(cx) identityToken := user.token.Encode()
if refresh, err := r.retrieveRefreshToken(cx, user); err == nil {
log.WithFields(log.Fields{ identityToken = refresh
"email": user.email, }
"client_ip": cx.ClientIP(), // step: delete all the cookies
"redirect": redirectURL, r.clearAllCookies(cx)
}).Infof("logging out the user: %s", user.email)
// step: check if the user has a state session and if so, revoke it // step: check if the user has a state session and if so, revoke it
rToken, err := r.retrieveRefreshToken(cx, user)
if err == nil {
if r.useStore() { if r.useStore() {
go func() {
if err := r.DeleteRefreshToken(user.token); err != nil { if err := r.DeleteRefreshToken(user.token); err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to remove the refresh token from store")
"error": err.Error(),
}).Errorf("unable to remove the refresh token from store")
} }
}()
} }
// step: the user has a offline session, we need to revoke the access and invalidate the the offline token // step: do we have a revocation endpoint?
if r.config.RevocationEndpoint != "" {
client, err := r.client.OAuthClient() client, err := r.client.OAuthClient()
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to retrieve the openid client")
"error": err.Error(),
}).Errorf("unable to retrieve the openid client")
cx.AbortWithStatus(http.StatusInternalServerError) cx.AbortWithStatus(http.StatusInternalServerError)
return return
} }
// step: construct the url for revocation // step: add the authentication headers
params := url.Values{} // @TODO need to add the authenticated request to go-oidc
params.Add("refresh_token", rToken) encodedID := url.QueryEscape(r.config.ClientID)
params.Add("token", rToken) encodedSecret := url.QueryEscape(r.config.ClientSecret)
request, err := http.NewRequest("POST", r.config.RevocationEndpoint, nil) // step: construct the url for revocation
request, err := http.NewRequest("POST", r.config.RevocationEndpoint,
bytes.NewBufferString(fmt.Sprintf("refresh_token=%s", identityToken)))
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"error": err.Error(), "error": err.Error(),
...@@ -294,29 +293,33 @@ func (r oauthProxy) logoutHandler(cx *gin.Context) { ...@@ -294,29 +293,33 @@ func (r oauthProxy) logoutHandler(cx *gin.Context) {
return return
} }
request.PostForm = params // step: add the authentication headers and content-type
request.SetBasicAuth(encodedID, encodedSecret)
request.Header.Set("Content-Type", "application/x-www-form-urlencoded") request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
// step: attempt to make the // step: attempt to make the
response, err := client.HttpClient().Do(request) response, err := client.HttpClient().Do(request)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to post to revocation endpoint")
"error": err.Error(),
}).Errorf("unable to post to revocation endpoint")
return return
} }
if response.StatusCode != http.StatusOK { // step: throw in a log
// step: read the response content if response.StatusCode != http.StatusNoContent {
content, _ := ioutil.ReadAll(response.Body) content, _ := ioutil.ReadAll(response.Body)
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"status": response.StatusCode, "status": response.StatusCode,
"response": fmt.Sprintf("%s", content), "response": fmt.Sprintf("%s", content),
}).Errorf("invalid response from revocation endpoint") }).Errorf("invalid response from revocation endpoint")
} else {
log.WithFields(log.Fields{
"user": user.email,
}).Infof("successfully logged out of the endpoint")
} }
} }
r.clearAllCookies(cx)
// step: should we redirect the user
if redirectURL != "" { if redirectURL != "" {
r.redirectToURL(redirectURL, cx) r.redirectToURL(redirectURL, cx)
return return
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment