Authentication and Authorization
Authentication mechanism
Definition(s):
Hardware or software-based mechanisms that force users to prove their identity before accessing data on a device.
Authentication
Is the act of validating that users are whom they claim to be.
( Confirms users are who they say they are)
This is the first step in any security process.
If a user enters the correct data, the system assumes the identity is valid and grants access.
- One-time pins. Grant access for only one session or transaction.
- Passwords. Usernames and passwords ****are the most common authentication factors.
- Authentication apps. Generate security codes via an outside party that grants access.
- Biometrics. A user presents a fingerprint or eye scan to gain access to the system.
Authorization
Is the process of giving the user permission to access a specific resource or function.
Authorization determines what resources a user can access.
Authorization always takes place after authentication.
authorization is the process of verifying what specific applications, files, and data a user has access to.
Authentication in Go
How authentication works
A client sends the authentication request to the server with the credentials.
The server validates the credentials with the database entry.
If the match is successful, it writes something called cookie ( Cookies are small pieces of text sent to your browser by a website you visit ) in the response.
This cookie will be sent back from the client in the subsequent requests to the server which is used by the servers to validate if the cookie attached is valid (on the basis of the one sent in the first place).
Sessions
A session is a way to record users authentication related payload in a cookie over a period of time.
When the user logs in in by sending valid credentials, the server attaches the cookie in the response.
Then the client uses that cookie (saved in the browser or client service) to make future requests.
When a client makes a logout request by sending a API on the server, the server destroys the session in the response.
The server can also place an expiration on cookies so that the session expires after a certain time if there is no activity.
Code example
package main
import (
"log"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
)
// dummy user data
var users = map[string]string{"user1": "password", "user2": "password"}
// creating a cookie session store
var store = sessions.NewCookieStore([]byte("secret_key"))
func main() {
r := mux.NewRouter()
r.HandleFunc("/login", loginHandler).Methods("POST")
r.HandleFunc("/logout", logoutHandler).Methods("GET")
r.HandleFunc("/healthcheck", healthcheck).Methods("GET")
// modifying http import struct to add an extra property
// of timeout (good practice)
httpServer := &http.Server{
Handler: r,
Addr: "127.0.0.1:8000",
WriteTimeout: 15 * time.Second,
}
log.Println("Server start at port 8000")
log.Fatal(httpServer.ListenAndServe())
}
func loginHandler(w http.ResponseWriter, r *http.Request) {
log.Println("loginHandler")
if r.Method != "POST" {
http.Error(w, "Method Not Supported", http.StatusMethodNotAllowed)
return
}
// ParseForm parses the raw query from the URL and updates r.Form
err := r.ParseForm()
if err != nil {
http.Error(w, "Please pass the data as URL form encoded", http.StatusBadRequest)
return
}
username := r.Form.Get("username")
password := r.Form.Get("password")
// check if user exists
storedPassword, exists := users[username]
if exists {
// Get registers and returns a session for the given name and session store.
// session.id is the name of the cookie that will be stored in the client's browser
session, _ := store.Get(r, "session.id")
if storedPassword == password {
session.Values["authenticated"] = true
// saves all sessions used during the current request
session.Save(r, w)
} else {
http.Error(w, "Invalid Credentials", http.StatusUnauthorized)
}
log.Println("Login successfully!")
w.Write([]byte("Login successfully!"))
}
}
func logoutHandler(w http.ResponseWriter, r *http.Request) {
// Get registers and returns a session for the given name and session store
// session.id is the name of the cookie that will be stored in the client's browser
session, _ := store.Get(r, "session.id")
// Set the authenticated value on the session to false
session.Values["authenticated"] = false
session.Save(r, w)
log.Println("Logout Successful")
w.Write([]byte("Logout Successful"))
}
func healthcheck(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session.id")
authenticated := session.Values["authenticated"]
if authenticated != nil && authenticated != false {
w.Write([]byte("Welcome!"))
return
} else {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
}