Example #1
0
// getClientIDFromAuthorizedRequest will extract the clientID from the bearer token.
func getClientIDFromAuthorizedRequest(r *http.Request) (string, error) {
	rawToken, err := oidc.ExtractBearerToken(r)
	if err != nil {
		return "", err
	}

	jwt, err := jose.ParseJWT(rawToken)
	if err != nil {
		return "", err
	}

	claims, err := jwt.Claims()
	if err != nil {
		return "", err
	}

	sub, ok, err := claims.StringClaim("sub")
	if err != nil {
		return "", fmt.Errorf("failed to parse 'sub' claim: %v", err)
	} else if !ok || sub == "" {
		return "", errors.New("missing required 'sub' claim")
	}

	return sub, nil
}
Example #2
0
func (l *TokenValidator) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	log.Info("validating")
	rawToken, err := oidc.ExtractBearerToken(r)
	if err != nil {
		log.Error("token.go: failed to get jwt from header")
		writeError(rw, http.StatusUnauthorized, "missing or invalid token")
		return
	}

	jwt, err := jose.ParseJWT(rawToken)
	if err != nil {
		log.Error("token.go: failed to parse jwt")
		writeError(rw, http.StatusUnauthorized, "missing or invalid token")
		return
	}

	err = l.accounts.Oidc.VerifyJWT(jwt)
	if err != nil {
		log.Errorf("token.go: Failed to verify signature: %v", err)
		writeError(rw, http.StatusUnauthorized, "invalid token")
	}

	claims, err := jwt.Claims()
	if err != nil {
		log.Error("token.go: failed to get claims", err)
		writeError(rw, http.StatusUnauthorized, "missing or invalid token")
		return
	}

	sub, ok, err := claims.StringClaim("sub")
	if err != nil {
		log.Errorf("token.go: failed to parse 'sub' claim: %v", err)
		writeError(rw, http.StatusUnauthorized, "missing or invalid token")
		return
	}
	if !ok || sub == "" {
		log.Error("token.go: missing required 'sub' claim")
		writeError(rw, http.StatusUnauthorized, "missing or invalid token")
		return
	}
	fmt.Println("token.go: verified token for", sub)
	r.Header.Set("sub", sub)
	next(rw, r)
}
Example #3
0
File: user.go Project: ryanj/dex
func (s *UserMgmtServer) getCreds(r *http.Request) (api.Creds, error) {
	token, err := oidc.ExtractBearerToken(r)
	if err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, api.ErrorUnauthorized
	}

	jwt, err := jose.ParseJWT(token)
	if err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, api.ErrorUnauthorized
	}

	claims, err := jwt.Claims()
	if err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, api.ErrorUnauthorized
	}

	clientID, ok, err := claims.StringClaim("aud")
	if err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, err
	}
	if !ok || clientID == "" {
		return api.Creds{}, errors.New("no aud(client ID) claim")
	}

	verifier := s.jwtvFactory(clientID)
	if err := verifier.Verify(jwt); err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, api.ErrorUnauthorized
	}

	sub, ok, err := claims.StringClaim("sub")
	if err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, err
	}
	if !ok || sub == "" {
		return api.Creds{}, api.ErrorUnauthorized
	}

	usr, err := s.um.Get(sub)
	if err != nil {
		if err == user.ErrorNotFound {
			return api.Creds{}, api.ErrorUnauthorized
		}
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, err
	}

	isAdmin, err := s.cir.IsDexAdmin(clientID)
	if err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, err
	}
	if !isAdmin {
		return api.Creds{}, api.ErrorForbidden
	}

	return api.Creds{
		ClientID: clientID,
		User:     usr,
	}, nil
}
Example #4
0
func (c *clientTokenMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	respondError := func() {
		writeAPIError(w, http.StatusUnauthorized, newAPIError(errorAccessDenied, "missing or invalid token"))
	}

	if c.keysFunc == nil {
		log.Errorf("Misconfigured clientTokenMiddleware, keysFunc is not set")
		respondError()
		return
	}

	if c.ciRepo == nil {
		log.Errorf("Misconfigured clientTokenMiddleware, ClientIdentityRepo is not set")
		respondError()
		return
	}

	rawToken, err := oidc.ExtractBearerToken(r)
	if err != nil {
		log.Errorf("Failed to extract token from request: %v", err)
		respondError()
		return
	}

	jwt, err := jose.ParseJWT(rawToken)
	if err != nil {
		log.Errorf("Failed to parse JWT from token: %v", err)
		respondError()
		return
	}

	keys, err := c.keysFunc()
	if err != nil {
		log.Errorf("Failed to get keys: %v", err)
		writeAPIError(w, http.StatusUnauthorized, newAPIError(errorAccessDenied, ""))
		respondError()
		return
	} else if len(keys) == 0 {
		log.Error("No keys available for verification in client token middleware")
		writeAPIError(w, http.StatusUnauthorized, newAPIError(errorAccessDenied, ""))
		respondError()
		return
	}

	ok, err := oidc.VerifySignature(jwt, keys)
	if err != nil {
		log.Errorf("Failed to verify signature: %v", err)
		respondError()
		return
	} else if !ok {
		log.Info("Invalid token")
		respondError()
		return
	}

	clientID, err := oidc.VerifyClientClaims(jwt, c.issuerURL)
	if err != nil {
		log.Errorf("Failed to verify JWT claims: %v", err)
		respondError()
		return
	}

	md, err := c.ciRepo.Metadata(clientID)
	if md == nil || err != nil {
		log.Errorf("Failed to find clientID: %s, error=%v", clientID, err)
		respondError()
		return
	}

	log.Infof("Authenticated token for client ID %s", clientID)
	c.next.ServeHTTP(w, r)
}
Example #5
0
File: user.go Project: Tecsisa/dex
func (s *UserMgmtServer) getCreds(r *http.Request, requiresAdmin bool) (api.Creds, error) {
	token, err := oidc.ExtractBearerToken(r)
	if err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, api.ErrorUnauthorized
	}

	jwt, err := jose.ParseJWT(token)
	if err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, api.ErrorUnauthorized
	}

	claims, err := jwt.Claims()
	if err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, api.ErrorUnauthorized
	}

	// The "aud" claim is allowed to be both a list of clients or a single client. Check for both cases.
	clientIDs, ok, err := claims.StringsClaim("aud")
	if err != nil || !ok {
		clientID, ok, err := claims.StringClaim("aud")
		if err != nil {
			log.Errorf("userMgmtServer: GetCreds failed to parse 'aud' claim: %q", err)
			return api.Creds{}, api.ErrorUnauthorized
		}
		if !ok || clientID == "" {
			return api.Creds{}, api.ErrorUnauthorized
		}
		clientIDs = []string{clientID}
	}
	if len(clientIDs) == 0 {
		log.Errorf("userMgmtServer: GetCreds err: no client in audience")
		return api.Creds{}, api.ErrorUnauthorized
	}

	// Verify that the JWT is signed by this server, has the correct issuer, hasn't expired, etc.
	// While we don't actualy care which client the token was issued for (we'll check that later),
	// go-oidc doesn't provide any methods which don't require passing a client ID.
	//
	// TODO(ericchiang): Add a verifier to go-oidc that doesn't require a client ID.
	verifier := s.jwtvFactory(clientIDs[0])
	if err := verifier.Verify(jwt); err != nil {
		log.Errorf("userMgmtServer: GetCreds err: failed to verify token %q", err)
		return api.Creds{}, api.ErrorUnauthorized
	}

	sub, ok, err := claims.StringClaim("sub")
	if err != nil {
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, err
	}
	if !ok || sub == "" {
		return api.Creds{}, api.ErrorUnauthorized
	}

	if s.allowClientCredsAuth && (len(clientIDs) == 1) && (sub == clientIDs[0]) {
		isAdmin, err := s.cm.IsDexAdmin(clientIDs[0])
		if err != nil {
			log.Errorf("userMgmtServer: GetCreds err: %q", err)
			return api.Creds{}, err
		}
		if requiresAdmin && !isAdmin {
			return api.Creds{}, api.ErrorForbidden
		}
		return api.Creds{
			ClientIDs: clientIDs,
		}, nil
	}

	usr, err := s.um.Get(sub)
	if err != nil {
		if err == user.ErrorNotFound {
			return api.Creds{}, api.ErrorUnauthorized
		}
		log.Errorf("userMgmtServer: GetCreds err: %q", err)
		return api.Creds{}, err
	}

	i := 0
	for _, clientID := range clientIDs {
		// Make sure the client actually exists.
		isAdmin, err := s.cm.IsDexAdmin(clientID)
		if err != nil {
			log.Errorf("userMgmtServer: GetCreds err: failed to get client %v", err)
			return api.Creds{}, err
		}

		// If the endpoint requires an admin client, filter out clients which are not admins.
		if requiresAdmin && !isAdmin {
			continue
		}

		clientIDs[i] = clientID
		i++
	}

	clientIDs = clientIDs[:i]
	if len(clientIDs) == 0 {
		return api.Creds{}, api.ErrorForbidden
	}

	return api.Creds{
		ClientIDs: clientIDs,
		User:      usr,
	}, nil
}