diff --git a/Documentation/api.md b/Documentation/api.md
index 39f404d3c7d468ca7a85e9e04d014080912761ac..a7a5612bc0b94a591c9735ea34904c46ba2f3d5a 100644
--- a/Documentation/api.md
+++ b/Documentation/api.md
@@ -15,6 +15,8 @@ grpc:
   # Server certs. If TLS credentials aren't provided dex will generate self-signed ones.
   tlsCert: /etc/dex/grpc.crt
   tlsKey: /etc/dex/grpc.key
+  # Client auth CA.
+  tlsClientCA: /etc/dex/client.crt
 ```
 
 ## Generating clients
diff --git a/cmd/dex/config.go b/cmd/dex/config.go
index b1beb850e7858252bd0ee415c546687e4e80cfd6..69b4f12ce71291bf6f0f3b2bc959e26750f14709 100644
--- a/cmd/dex/config.go
+++ b/cmd/dex/config.go
@@ -88,9 +88,10 @@ type Web struct {
 // GRPC is the config for the gRPC API.
 type GRPC struct {
 	// The port to listen on.
-	Addr    string `yaml:"addr"`
-	TLSCert string `yaml:"tlsCert"`
-	TLSKey  string `yaml:"tlsKey"`
+	Addr        string `yaml:"addr"`
+	TLSCert     string `yaml:"tlsCert"`
+	TLSKey      string `yaml:"tlsKey"`
+	TLSClientCA string `yaml:"tlsClientCA"`
 }
 
 // Storage holds app's storage configuration.
diff --git a/cmd/dex/serve.go b/cmd/dex/serve.go
index b3ccba92f5f2e9c40ea7b0a6c3389d315ed1111e..489a20c0f1e202617fc15ae3eeaa8c41dc4bc55f 100644
--- a/cmd/dex/serve.go
+++ b/cmd/dex/serve.go
@@ -1,6 +1,8 @@
 package main
 
 import (
+	"crypto/tls"
+	"crypto/x509"
 	"errors"
 	"fmt"
 	"io/ioutil"
@@ -67,6 +69,7 @@ func serve(cmd *cobra.Command, args []string) error {
 		{c.GRPC.TLSCert != "" && c.GRPC.Addr == "", "no address specified for gRPC"},
 		{c.GRPC.TLSKey != "" && c.GRPC.Addr == "", "no address specified for gRPC"},
 		{(c.GRPC.TLSCert == "") != (c.GRPC.TLSKey == ""), "must specific both a gRPC TLS cert and key"},
+		{c.GRPC.TLSCert == "" && c.GRPC.TLSClientCA != "", "cannot specify gRPC TLS client CA without a gRPC TLS cert"},
 	}
 
 	for _, check := range checks {
@@ -77,11 +80,36 @@ func serve(cmd *cobra.Command, args []string) error {
 
 	var grpcOptions []grpc.ServerOption
 	if c.GRPC.TLSCert != "" {
-		opt, err := credentials.NewServerTLSFromFile(c.GRPC.TLSCert, c.GRPC.TLSKey)
-		if err != nil {
-			return fmt.Errorf("load grpc certs: %v", err)
+		if c.GRPC.TLSClientCA != "" {
+			// Parse certificates from certificate file and key file for server.
+			cert, err := tls.LoadX509KeyPair(c.GRPC.TLSCert, c.GRPC.TLSKey)
+			if err != nil {
+				return fmt.Errorf("parsing certificate file: %v", err)
+			}
+
+			// Parse certificates from client CA file to a new CertPool.
+			cPool := x509.NewCertPool()
+			clientCert, err := ioutil.ReadFile(c.GRPC.TLSClientCA)
+			if err != nil {
+				return fmt.Errorf("reading from client CA file: %v", err)
+			}
+			if cPool.AppendCertsFromPEM(clientCert) != true {
+				return errors.New("failed to parse client CA")
+			}
+
+			tlsConfig := tls.Config{
+				Certificates: []tls.Certificate{cert},
+				ClientAuth:   tls.RequireAndVerifyClientCert,
+				ClientCAs:    cPool,
+			}
+			grpcOptions = append(grpcOptions, grpc.Creds(credentials.NewTLS(&tlsConfig)))
+		} else {
+			opt, err := credentials.NewServerTLSFromFile(c.GRPC.TLSCert, c.GRPC.TLSKey)
+			if err != nil {
+				return fmt.Errorf("load grpc certs: %v", err)
+			}
+			grpcOptions = append(grpcOptions, grpc.Creds(opt))
 		}
-		grpcOptions = append(grpcOptions, grpc.Creds(opt))
 	}
 
 	connectors := make([]server.Connector, len(c.Connectors))
diff --git a/examples/config-dev.yaml b/examples/config-dev.yaml
index 9f2885f08c5b97f4fef775207d2ed8053c7070a4..84af2fbb1f088354663a2ccd9a7da3d28b7f0601 100644
--- a/examples/config-dev.yaml
+++ b/examples/config-dev.yaml
@@ -22,6 +22,7 @@ web:
 #   addr: 127.0.0.1:5557
 #   tlsCert: /etc/dex/grpc.crt
 #   tlsKey: /etc/dex/grpc.key
+#   tlsClientCA: /etc/dex/client.crt
 
 # Instead of reading from an external storage, use this list of clients.
 #