Golang : Basic authentication with .htpasswd file
If you are looking to protect a web page with Basic Authentication. It can be done easily with Golang. In this tutorial, we will first explore how to implement basic authentication with username and password in the source code. Follow by sourcing the username/password from the .htpasswd
file.
This code example will prompt a user for username and password before allowing access.
package main
import (
"encoding/base64"
"github.com/gorilla/mux"
"net/http"
"strings"
)
var username = []byte("hello")
var password = []byte("password")
func BasicAuth(w http.ResponseWriter, r *http.Request, user, pass []byte) bool {
s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
if len(s) != 2 {
return false
}
b, err := base64.StdEncoding.DecodeString(s[1])
if err != nil {
return false
}
pair := strings.SplitN(string(b), ":", 2)
if len(pair) != 2 {
return false
}
return pair[0] == string(user) && pair[1] == string(pass)
}
func Home(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
}
func Protected(w http.ResponseWriter, r *http.Request) {
// pass from global variables
if BasicAuth(w, r, username, password) {
w.Write([]byte("Welcome to the Protected Page!!"))
return
}
w.Header().Set("WWW-Authenticate", `Basic realm="Beware! Protected REALM! "`)
w.WriteHeader(401)
w.Write([]byte("401 Unauthorized\n"))
}
func main() {
mx := mux.NewRouter()
mx.HandleFunc("/", Home)
mx.HandleFunc("/protectedpage/", Protected)
http.ListenAndServe(":8080", mx)
}
run this code and point your browser to http://localhost:8080/protectedpage/
. You will be prompted for the username and password, which is hello
and password
.
If you are looking for more secure option, you can choose to load the username and password from .htpasswd
file.
Use http://www.htaccesstools.com/htpasswd-generator/ to generate a .htpasswd
file. In this example, we will use username
and password
Make sure the file has only 1 line.
cat .htpasswd
username:$apr1$F9tXeu9r$oairgF8rFh2oRUC4Dl9v/1
We will read the .htpasswd
file with the github.com/abbot/go-http-auth
package.
Run this code and point your browser to http://localhost:8080/protectedpage/
. You will be prompted for the username and password, which is username
and password
.
package main
import (
"fmt"
auth "github.com/abbot/go-http-auth"
"github.com/gorilla/mux"
"net/http"
)
func Home(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
}
func Protected(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
w.Write([]byte(fmt.Sprintf("Hello, %s!", r.Username)))
}
func main() {
// read from .htpasswd file
htpasswd := auth.HtpasswdFileProvider("./.htpasswd")
authenticator := auth.NewBasicAuthenticator("Basic Realm", htpasswd)
mx := mux.NewRouter()
mx.HandleFunc("/", Home)
mx.HandleFunc("/protectedpage/", authenticator.Wrap(Protected))
http.ListenAndServe(":8080", mx)
}
The outcome should be the same as the previous code, except that this time, the username and password taken from a file instead of hard coded into the source code.
References :
See also : Golang : How to implement two-factor authentication?
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+7.1k CloudFlare : Another way to get visitor's real IP address
+9.2k Golang : How to check if a string with spaces in between is numeric?
+8.7k Golang : On lambda, anonymous, inline functions and function literals
+5.4k Golang : Stop goroutine without channel
+7.3k Golang : Scanf function weird error in Windows
+9.9k Golang : Get escape characters \u form from unicode characters
+14k Golang : Fix cannot use buffer (type bytes.Buffer) as type io.Writer(Write method has pointer receiver) error
+6.1k Linux/Unix : Commands that you need to be careful about
+4.6k MariaDB/MySQL : How to get version information
+14.2k Golang : Convert IP version 6 address to integer or decimal number
+5.9k Golang : Use NLP to get sentences for each paragraph example
+3.3k Golang : Fix go-cron set time not working issue