Hello, in today’s article, I will show you how you can build your own OAuth2 server just like google, facebook, github etc. This will be very helpful if you want to build a production ready public or private API. So let’s get started. What is OAuth2? Open Authorization Version 2.0 is known as OAuth2. It’s one kind of protocol or framework to secure RESTful Web Services. OAuth2 is very powerful. Now a days, majority of the REST API are protected with OAuth2 due to it’s rock solid security. OAuth2 has two parts 01. Client 02. Server OAuth2 Client If you’re familiar with this screen, you know what I’m talking about. Anyway, Let me explain the story behind the image: You’re building a user facing application that works with user’s github repositories. For example: CI tools like TravisCI, CircleCI, Drone etc. But user’s github account is secured and no one can access it if the owner doesn’t want. So how do these CI tools access user’s github account and repositories? Easy. Your application will ask the user “In order to work with us, you need to give read access to your github repos. Do you agree?” Then the user will say “Yes I do. And do whatever needs to do”. Then your application will contact github’s authority to grant access to that particular user’s github account. Github will check if it’s true and ask that user to authorize. Then github will issue an ephemeral token to the client. Now, when your application needs to access it after the authentication and authorization, it needs to send the access token with the request so that github will think: “Oh, the access token looks familiar, may be we have given that to you. Ok, you can access” That’s the long story. Days have changed, now you don’t need to go to github authority physically each time (we never had to do that). Everything can be done automatically. But how? This is a UML sequence diagram of what I have talked couple of minutes ago. Just graphical representation. From the above picture, we found some important things. OAuth2 has 4 roles: 01. User — The end user who will use your application 02. Client — The application you’re building that will use github account and the user will use 03. Auth Server — The server that deals with the main OAuth things 04. Resource Server — The server that has the protected resources. For example github Client sends OAuth2 request to the auth server on behalf of the user. Building an OAuth2 client is neither easy nor hard. Sounds funny, right? We’ll do that in the next part. But in this part, we’ll go to the other side of the world. We’ll build our own OAuth2 Server. Which is not easy but juicy. Ready? Let’s go OAuth2 Server You may ask me “Wait a minute Cyan, why building an OAuth2 server?” Did you forget man? I have said this earlier. Ok, let me tell you again. Imagine, you’re building a very useful application that gives accurate weather information (there are plenty of this kind of api out there). Now you want to make it open so that public can use it or you want to make money with it. Whatever the case is, you need to protect your resources from un-authorized access or malicious attacks. In order to do that you need to secure your API resources. Here comes the OAuth2 thingy. Bingo! From the picture above, we can see that we need place an Auth Server in front of our REST API Resource Server. That’s what we’re talking about. The Auth Server will be built using OAuth2 specification. Then we’ll become the github of the first picture, hahahaha just kidding. The primary goal of the OAuth2 server is to provide access token to the client. That’s why OAuth2 Server is also known as OAuth2 Provider, because they provide token. Enough talking. There are four types of OAuth2 server based of the Grant Flow type: 01. Authorization Code Grant 02. Implicit Grant 03. Client Credentials Grant 04. Password Grant If you want to know more about OAuth2, check out awesome article. this For this article, we’ll use . So let’s dig in Client Credentials Grant Type Client Credentials Grant Flow Based Server When implementing Client Credentials Grant Flow based OAuth2 Server, we need to know couple of things. In this grant type, there’s no user interaction (i.e. signup, sign-in). Two things needed, and they are the and the . With this two things, we can obtain . Client is the 3rd party application. When you need to access resource server without the user or only by the client application, then this grant type is simple and best suited. client_id client_secret access_token Here’s a UML Sequence Diagram of it. Coding To build this, we need to rely on an awesome Go package First of all, let’s build a simple API server as Resource Server package main ( ) func main() { http.HandleFunc( , func(w http.ResponseWriter, r *http.Request) { w.Write([]byte( )) }) log.Fatal(http.ListenAndServe( , nil)) import "log" "net/http" "/protected" "Hello, I'm protected" ":9096" Run the server and send a Get Request to http://localhost:9096/protected You’ll get response. What kind of protected server it is? Though the endpoint name is protected, but anyone can access it. So we need to protect it with OAuth2. Now we’ll write our authorization server Routes 01. for issuing client credentials (client_id and client_secret) /credentials 03. to issue token with client credentials /token We need to implement these two routes. Here’s the preliminary setup package main ( ) func main() { := manage.NewDefaultManager() manager.SetAuthorizeCodeTokenCfg(manage.DefaultAuthorizeCodeTokenCfg) manager.MustTokenStorage(store.NewMemoryTokenStore()) clientStore := store.NewClientStore() manager.MapClientStorage(clientStore) srv := server.NewDefaultServer(manager) srv.SetAllowGetAccessRequest( ) srv.SetClientInfoHandler(server.ClientFormHandler) manager.SetRefreshTokenCfg(manage.DefaultRefreshTokenCfg) srv.SetInternalErrorHandler(func(err error) (re *errors.Response) { log.Println( , err.Error()) }) srv.SetResponseErrorHandler(func(re *errors.Response) { log.Println( , re.Error.Error()) }) http.HandleFunc( , func(w http.ResponseWriter, r *http.Request) { w.Write([]byte( )) }) log.Fatal(http.ListenAndServe( , nil)) } import "encoding/json" "fmt" "github.com/google/uuid" "gopkg.in/oauth2.v3/models" "log" "net/http" "time" "gopkg.in/oauth2.v3/errors" "gopkg.in/oauth2.v3/manage" "gopkg.in/oauth2.v3/server" "gopkg.in/oauth2.v3/store" manager true "Internal Error:" return "Response Error:" "/protected" "Hello, I'm protected" ":9096" Here we created one manager, client store and the auth server itself. Here’s the route /credentials http.HandleFunc( , func(w http.ResponseWriter, r *http.Request) { := uuid.New().String()[: ] clientSecret := uuid.New().String()[: ] err := clientStore.Set(clientId, &models.Client{ : clientId, : clientSecret, : , }) err != nil { fmt.Println(err.Error()) } w.Header().Set( , ) json.NewEncoder(w).Encode(map[string]string{ : clientId, : clientSecret}) }) "/credentials" clientId 8 8 ID Secret Domain "http://localhost:9094" if "Content-Type" "application/json" "CLIENT_ID" "CLIENT_SECRET" It creates two random string, one for client_id and another for client_secret. Then saves them to the client store. And return them as response. That’s it. We used in memory store, but we can store them in redis, mongodb, postgres etc. Here’s the route: /token http.HandleFunc( , func(w http.ResponseWriter, r *http.Request) { srv.HandleTokenRequest(w, r) }) "/token" It’s very simple. It passes the request and response to the appropriate handler so that the server can decode all the necessary data from the request payload. So here’s our overall code: package main ( ) func main() { := manage.NewDefaultManager() manager.SetAuthorizeCodeTokenCfg(manage.DefaultAuthorizeCodeTokenCfg) manager.MustTokenStorage(store.NewMemoryTokenStore()) clientStore := store.NewClientStore() manager.MapClientStorage(clientStore) srv := server.NewDefaultServer(manager) srv.SetAllowGetAccessRequest( ) srv.SetClientInfoHandler(server.ClientFormHandler) manager.SetRefreshTokenCfg(manage.DefaultRefreshTokenCfg) srv.SetInternalErrorHandler(func(err error) (re *errors.Response) { log.Println( , err.Error()) }) srv.SetResponseErrorHandler(func(re *errors.Response) { log.Println( , re.Error.Error()) }) http.HandleFunc( , func(w http.ResponseWriter, r *http.Request) { srv.HandleTokenRequest(w, r) }) http.HandleFunc( , func(w http.ResponseWriter, r *http.Request) { := uuid.New().String()[: ] clientSecret := uuid.New().String()[: ] err := clientStore.Set(clientId, &models.Client{ : clientId, : clientSecret, : , }) err != nil { fmt.Println(err.Error()) } w.Header().Set( , ) json.NewEncoder(w).Encode(map[string]string{ : clientId, : clientSecret}) }) http.HandleFunc( , func(w http.ResponseWriter, r *http.Request) { w.Write([]byte( )) }) log.Fatal(http.ListenAndServe( , nil)) } import "encoding/json" "fmt" "github.com/google/uuid" "gopkg.in/oauth2.v3/models" "log" "net/http" "time" "gopkg.in/oauth2.v3/errors" "gopkg.in/oauth2.v3/manage" "gopkg.in/oauth2.v3/server" "gopkg.in/oauth2.v3/store" manager true "Internal Error:" return "Response Error:" "/token" "/credentials" clientId 8 8 ID Secret Domain "http://localhost:9094" if "Content-Type" "application/json" "CLIENT_ID" "CLIENT_SECRET" "/protected" "Hello, I'm protected" ":9096" Run the code and go to route to register and get client_id and client_secret http://localhost:9096/credentials Now go to this URL http://localhost:9096/token?grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=all You”ll get the access_token with expiry time and some other information. Now we got our access_token. But our /protected route is still un-protected. We need to setup a way that will check if a valid token exists with each client request. If yes, then we give the client access. Otherwise not. We can do this with a middleware. Writing middleware in go is ao much fun if you know what you are doing. Here’s the middleware: func validateToken(f http.HandlerFunc, srv *server.Server) http.HandlerFunc { http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, := srv.ValidationBearerToken(r) err != nil { http.Error(w, err.Error(), http.StatusBadRequest) } f.ServeHTTP(w, r) }) } return err if return This will check if a valid token is given with the request and take action based on that. Now we need to put this middleware in front of our /protected route using adapter/decorator pattern http.HandleFunc( , validateToken(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte( )) }, srv)) "/protected" "Hello, I'm protected" Now the whole code looks like this: package main ( ) func main() { := manage.NewDefaultManager() manager.SetAuthorizeCodeTokenCfg(manage.DefaultAuthorizeCodeTokenCfg) manager.MustTokenStorage(store.NewMemoryTokenStore()) clientStore := store.NewClientStore() manager.MapClientStorage(clientStore) srv := server.NewDefaultServer(manager) srv.SetAllowGetAccessRequest( ) srv.SetClientInfoHandler(server.ClientFormHandler) manager.SetRefreshTokenCfg(manage.DefaultRefreshTokenCfg) srv.SetInternalErrorHandler(func(err error) (re *errors.Response) { log.Println( , err.Error()) }) srv.SetResponseErrorHandler(func(re *errors.Response) { log.Println( , re.Error.Error()) }) http.HandleFunc( , func(w http.ResponseWriter, r *http.Request) { srv.HandleTokenRequest(w, r) }) http.HandleFunc( , func(w http.ResponseWriter, r *http.Request) { := uuid.New().String()[: ] clientSecret := uuid.New().String()[: ] err := clientStore.Set(clientId, &models.Client{ : clientId, : clientSecret, : , }) err != nil { fmt.Println(err.Error()) } w.Header().Set( , ) json.NewEncoder(w).Encode(map[string]string{ : clientId, : clientSecret}) }) http.HandleFunc( , validateToken(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte( )) }, srv)) log.Fatal(http.ListenAndServe( , nil)) } func validateToken(f http.HandlerFunc, srv *server.Server) http.HandlerFunc { http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, := srv.ValidationBearerToken(r) err != nil { http.Error(w, err.Error(), http.StatusBadRequest) } f.ServeHTTP(w, r) }) } import "encoding/json" "fmt" "github.com/google/uuid" "gopkg.in/oauth2.v3/models" "log" "net/http" "time" "gopkg.in/oauth2.v3/errors" "gopkg.in/oauth2.v3/manage" "gopkg.in/oauth2.v3/server" "gopkg.in/oauth2.v3/store" manager // token memory store // client memory store true "Internal Error:" return "Response Error:" "/token" "/credentials" clientId 8 8 ID Secret Domain "http://localhost:9094" if "Content-Type" "application/json" "CLIENT_ID" "CLIENT_SECRET" "/protected" "Hello, I'm protected" ":9096" return err if return Now run the server and try to access endpoint without the as URL Query. Then try to give wrong . Either way, the auth server will stop you. /protected access_token access_token Now get the and again from the server and send request to the protected endpoint : credentials access_token http://localhost:9096/test?access_token=YOUR_ACCESS_TOKEN Bingo! You’ll get access to it. So we’ve learned how to setup our own OAuth2 Server using Go. In the next part, we’ll build our OAuth2 client in Go. And in the last part, we’ll build the with user login and authorization. Authorization Code Grant Type Based Server