Intro
I will try implementing HTTP Authentication with 'Basic' HTTP Authentication.
After authentication, I will set a session key as a cookie value.
Note:
This sample was created simply to see how "Basic" authentication works.
In practice, security measures must be applied.
'Basic' HTTP Authentication
'Basic' HTTP Authentication uses a pair of ID and password for authentication.
And it's based on "Challenge-response authentication".
- [Client] Access the protected resources
- [Server] Because the client does not have the credentials、The server returns a 401 status code and "WWW-Authenticate".
- [Client] Send valid ID and password
- [Server] The authentication is succeeded and the server will return the protected resources
2. Returning a 401 status code and "WWW-Authenticate"
At first I will see how web browsers work when the server returns the 401 statu code.
main.go
package main
import (
"log"
"net/http"
)
func main() {
// It only returns 401 status code now.
http.HandleFunc("/auth/", func(w http.ResponseWriter, r *http.Request) {
// TODO: Validate the user authentication info
// At least one "WWW-Authenticate" is required.
// Otherwise, web browsers just show the default 401 error page.
w.Header().Set("WWW-Authenticate", "Basic realm=\"localhost\"")
w.WriteHeader(401)
})
log.Fatal(http.ListenAndServe("localhost:8083", nil))
}
Result
4. Get the client user-pass(ID and password)
After the client input its ID and password, the server can get them from HTTP request header.
The web brower sets them into HTTP request header as "user-pass".
The "user-pass" is generated in the following format and encoded in Base64.
{ID}:{Password}
The web browser registers it with the "Authorization" key along with the Scheme.
Basic {user-pass}
The server can split them into the Scheme(Basic), the ID, and the password.
main.go
...
import (
"encoding/base64"
"log"
"net/http"
"strings"
)
...
func signin(r *http.Request) {
// Get user-pass
authText := r.Header.Get("Authorization")
splitted := strings.Split(authText, " ")
if len(splitted) >= 2 {
log.Printf("Authorization: %s UserPass: %s", splitted[0], splitted[1])
decoded, err := base64.StdEncoding.DecodeString(splitted[1])
if err == nil {
userPass := string(decoded)
splitTarget := strings.Index(userPass, ":")
if splitTarget < 0 {
log.Println("Invalid")
return
}
userId := userPass[0:splitTarget]
pass := userPass[splitTarget+1:]
log.Printf("USER ID:%s Password:%s", userId, pass)
} else {
log.Println(err.Error())
}
} else {
log.Println("Invalid")
}
}
Results
Authorization: Basic UserPass: ZmZmZ2hqazpkZmdoamts
USER ID:fffghjk Password:dfghjkl
Saving the authentication info
After authentication, how should I keep my credentials?
For example, ASP.NET Core Identity registers authentication information in cookies by default.
I will try registering in cookies in this time.
According to my ASP.NET Core application run, the cookie set after authentication was as follows.
Cookie: .AspNetCore.Identity.Application=CfDJ8PAT8IN6xqxGqh9UWuW_Iif6kvwPRUoA5MEVumnp6qYnZySdcFGwZhWqaznPiKtjbsiyfYLzPmyKHs_wSDYZqSp61aiv-wzRYg5zuisGsOyVpSbKrCUkxUMSTQIrXFdNeVMdb7QDQYJahbbdgjSmZc5kOAuqK8WQh1fCQ0GxbE4XrvwEDClLm-SSRyOC72Ne76uBnGRHPzuGOFXUMklWeRcRWLPEd3ZOwMkwChKkSMA7xJjHAPtCnx0LLkZJ30YmfsbRPJ6qBWiSCoq-ChVzWZLKog0mR4SLBz7K_dEbUfdfMeAi52sXiJkk8rHSaHxxDymF4KJu8-Qg6xZ4e--02xCc-dFedut7Q2NXQPXD7PXY_wV-VB0x60KRQYNc_UeZDvuZWPZi-vgICqgraMFHoynKLEQgRbmTYU6SVRb_MX920fccmtySo8y5-xZ6P_Drmko1hqNyyZKamMKxqHxXXXX
Because I couldn't find a standard specification for storing authentication information in cookies, I figured I had to decide for myself what the key and value of the cookie would be.
Set cookies
expiration := time.Now()
expiration = expiration.AddDate(0, 0, 1)
cookie := http.Cookie{Name: "WebAuthSample", Value: uuid.New().String(), Expires: expiration}
http.SetCookie(w, &cookie)
Get cookies
func getAuthenticationInfo(r *http.Request) string {
for _, c := range r.Cookies() {
if c.Name != "WebAuthSample" {
continue
}
// If the client has a valid cookie, it can retrieve the value.
return c.String()
}
return ""
}
TODO
The server-side application should maintain the ID and cookie values of clients who have completed the authentication process, and check the authentication status when the client accesses protected resources.
Top comments (0)