Skip to content

Commit 7f49849

Browse files
committed
Initial. API with JWT Authentication
0 parents  commit 7f49849

36 files changed

+2344
-0
lines changed

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Created by https://www.gitignore.io
2+
3+
### Go ###
4+
# Compiled Object files, Static and Dynamic libs (Shared Objects)
5+
*.o
6+
*.a
7+
*.so
8+
9+
# Folders
10+
_obj
11+
_test
12+
13+
# Architecture specific extensions/prefixes
14+
*.[568vq]
15+
[568vq].out
16+
17+
*.cgo1.go
18+
*.cgo2.c
19+
_cgo_defun.c
20+
_cgo_gotypes.go
21+
_cgo_export.*
22+
23+
_testmain.go
24+
25+
*.exe
26+
*.test
27+
*.prof
28+
.vagrant

Vagrantfile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# -*- mode: ruby -*-
2+
# vi: set ft=ruby :
3+
4+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
5+
VAGRANTFILE_API_VERSION = "2"
6+
7+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
8+
# Every Vagrant virtual environment requires a box to build off of.
9+
config.vm.box = "https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box"
10+
config.vm.synced_folder '.', '/home/vagrant/go/src/api.jwt.auth/'
11+
12+
13+
# Create a forwarded port mapping which allows access to a specific port
14+
# within the machine from a port on the host machine. In the example below,
15+
# accessing "localhost:8080" will access port 80 on the guest machine.
16+
#config.vm.network "forwarded_port", guest: 8000, host: 8080
17+
18+
# Create a public network, which generally matched to bridged network.
19+
# Bridged networks make the machine appear as another physical device on
20+
# your network.
21+
config.vm.network "public_network", ip: "192.168.1.210"
22+
23+
config.vm.provision "ansible" do |ansible|
24+
ansible.playbook = "provision/playbook.yml"
25+
ansible.host_key_checking = false
26+
ansible.verbose = "vvvv"
27+
end
28+
29+
end

api/parameters/auth.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package parameters
2+
3+
import ()
4+
5+
type TokenAuthentication struct {
6+
Token string `json:"token" form:"token"`
7+
}

controllers/auth_controller.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package controllers
2+
3+
import (
4+
"api.jwt.auth/api/parameters"
5+
"api.jwt.auth/core/authentication"
6+
"api.jwt.auth/services/models"
7+
"encoding/json"
8+
"net/http"
9+
)
10+
11+
func Login(w http.ResponseWriter, r *http.Request) {
12+
request_user := new(models.User)
13+
decoder := json.NewDecoder(r.Body)
14+
decoder.Decode(&request_user)
15+
16+
authBackend := authentication.InitJWTAuthenticationBackend()
17+
18+
if authBackend.Authenticate(request_user) {
19+
token := parameters.TokenAuthentication{authBackend.GenerateToken()}
20+
response, _ := json.Marshal(token)
21+
w.Header().Set("Content-Type", "application/json")
22+
w.Write(response)
23+
24+
} else {
25+
w.Header().Set("Content-Type", "application/json")
26+
w.WriteHeader(http.StatusUnauthorized)
27+
w.Write([]byte("Unauthorized"))
28+
}
29+
}
30+
31+
func RefresfhToken(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
32+
authBackend := authentication.InitJWTAuthenticationBackend()
33+
token := parameters.TokenAuthentication{authBackend.GenerateToken()}
34+
response, _ := json.Marshal(token)
35+
w.Header().Set("Content-Type", "application/json")
36+
w.Write(response)
37+
}
38+
39+
func Logout(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
40+
w.Write([]byte("Unauthorized"))
41+
}

controllers/hello_controller.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package controllers
2+
3+
import (
4+
"net/http"
5+
)
6+
7+
func HelloController(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
8+
w.Write([]byte("Hello, World!"))
9+
}

core/authentication/jwt_backend.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package authentication
2+
3+
import (
4+
"api.jwt.auth/services/models"
5+
jwt "github.com/dgrijalva/jwt-go"
6+
"golang.org/x/crypto/bcrypt"
7+
"io/ioutil"
8+
"path/filepath"
9+
)
10+
11+
type JWTAuthenticationBackend struct {
12+
privateKey []byte
13+
PublicKey []byte
14+
}
15+
16+
func InitJWTAuthenticationBackend() *JWTAuthenticationBackend {
17+
authBack := new(JWTAuthenticationBackend)
18+
privateKeyPath, _ := filepath.Abs("./core/authentication/keys/private_key")
19+
publicKeyPath, _ := filepath.Abs("./core/authentication/keys/public_key.pub")
20+
authBack.privateKey, _ = ioutil.ReadFile(privateKeyPath)
21+
authBack.PublicKey, _ = ioutil.ReadFile(publicKeyPath)
22+
23+
return authBack
24+
}
25+
26+
func (backend *JWTAuthenticationBackend) GenerateToken() string {
27+
token := jwt.New(jwt.GetSigningMethod("RS256"))
28+
tokenString, _ := token.SignedString(backend.privateKey)
29+
return tokenString
30+
}
31+
32+
func (backend *JWTAuthenticationBackend) Authenticate(user *models.User) bool {
33+
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte("testing"), 10)
34+
35+
testUser := models.User{
36+
Username: "haku",
37+
Password: string(hashedPassword),
38+
}
39+
40+
return user.Username == testUser.Username && bcrypt.CompareHashAndPassword([]byte(testUser.Password), []byte(user.Password)) == nil
41+
}
42+
43+
func (backend *JWTAuthenticationBackend) Logout(token string) error {
44+
return nil
45+
}

core/authentication/keys/private_key

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEowIBAAKCAQEA4w5xhil8YFSLptRxzQsiJgQm7DxfVx7nEFAndQDw/7a1VfIf
3+
hhzZlUYx6u+57kP4+JPhqLMl9hEPnJh2DMPV4wrQAOSe6pDK5UP/xZQx8ygy70lG
4+
fJ6MVo7mkXKaofKobOhkFIOhqtLU/6CrzFl+KdFIsD7pt+FxV6mMmPbnAvDN+hF5
5+
NwU6N61WGAZER8z7SSTgayGpuHdUKCdPwfuiUIEX3GxhskzV/ROiS+R/NbQZlsfm
6+
QqcBJ5FxhOtAVevi9s7x6LLTSQKopuuunSTTtu3ys/hs5m6AqNPPkLKqp6R8iXF1
7+
Lg0DMeQlFHYwEo3oRweMNhfYRzC3ukioSf+GuwIDAQABAoIBADlemeKLMujoE80Y
8+
WpSzXnJ6lBcWfgR2Q23EwuN2VG5YDONlZP+u5G8qKEyzO6hvNkYgn2DPuyS8VNR9
9+
VT6OcMmIHtxK57he01UwZDzY3/IPUydQvWWZbd4lBy7y5Q1MUbAK29avF7cgxD6+
10+
qwncBtusDJCzpLwYU1oR9ftkTyRXl8WzHUQ+/QILNnSCDsTrP8JsVaVxbd6FhKKn
11+
5sSyqM+dX7mtvVAOcj0OJSHZiit7fk5QG9Pi/5iP4pCdZf42sImsr++2GFOezfJd
12+
H5UU+ujTf+b4oGirnqgEDRrSr5IyykagWc07D2KJgyPzrkfFDxoB5C/ZC3C6C9AA
13+
Xwzd+GECgYEA5SPDfCMVBRFkYBoxKgbWEElquGiPMDSe+p6QSlX24UXFv8gzdtbT
14+
f33d27v2cpIOWYym3Er5JiSFq6oCr1cg9+mLP/tNc50sHrdHb8vRfn190nawFJHa
15+
eOe0b3ZePUtAxdd1HaZgq4bNnLYSbi//spdHuu6E1jZrzcmbvIm7PJECgYEA/awp
16+
rILMDvqHuGNlVr+kdcGfmFxA8y9Z1tZHLgqNjPQQlaOuyJn1cfYbIqghMLjk//Au
17+
VQ5gfKLc2abHQaVQ2dLqV846eNQvr+cnLQUrUqk41IZuN0HTMbvLHgOLkQNdsUMs
18+
1TmmPeMxh9X9cLqp7mZoY5CeWeWFOe3EJA1dZIsCgYEAklbf3yUMpJrx7wprQbrx
19+
9Z7dwH5OjGve6JJh9oemT0LfQ1dZvtj+ZBr/mPkXMR6keX6Bhol/S2Ph1ruSUWck
20+
0A/gdfFKCr9jUQ6eWgDif5UnyUUxuUFZNQRN0S3Yi+7GpFOxIUmDzagfIqmJZcPT
21+
2rwQ/IqeXayN9vR+ONABu3ECgYAECn4PdXXytyL6WPsASsU/6vmz36RZO2Pe/ELe
22+
BOUEXc7100mxgGJckmMURkFhGVDsktLqH/SBh8ak4PdDoHKNRcLd6zcbPaYU00XY
23+
fcCW7IMvP4T59F586FTwAXZztO4FKODJ9MUlLz1WwJ3s8cxLM+5tx5v+Kp3YsmTx
24+
fhUCyQKBgDCEkFexrqC2a1rHLh+pwTyvnE4JCVNt72FF8L51aEsG5tGGFvTvgUN6
25+
IlRCYASNhUK/3+hu337uOSolKXu0W+dFnp1/OLo6sUkuhxWGx3YLwGJygjSrOl5f
26+
3wIikQ0U/RjRr+/pI0/yw/w3Xcr7iUjei6SBxkiIeZL/749EcLNB
27+
-----END RSA PRIVATE KEY-----
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4w5xhil8YFSLptRxzQsi
3+
JgQm7DxfVx7nEFAndQDw/7a1VfIfhhzZlUYx6u+57kP4+JPhqLMl9hEPnJh2DMPV
4+
4wrQAOSe6pDK5UP/xZQx8ygy70lGfJ6MVo7mkXKaofKobOhkFIOhqtLU/6CrzFl+
5+
KdFIsD7pt+FxV6mMmPbnAvDN+hF5NwU6N61WGAZER8z7SSTgayGpuHdUKCdPwfui
6+
UIEX3GxhskzV/ROiS+R/NbQZlsfmQqcBJ5FxhOtAVevi9s7x6LLTSQKopuuunSTT
7+
tu3ys/hs5m6AqNPPkLKqp6R8iXF1Lg0DMeQlFHYwEo3oRweMNhfYRzC3ukioSf+G
8+
uwIDAQAB
9+
-----END PUBLIC KEY-----

core/authentication/middlewares.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package authentication
2+
3+
import (
4+
jwt "github.com/dgrijalva/jwt-go"
5+
"net/http"
6+
)
7+
8+
func RequireTokenAuthentication(rw http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
9+
authBackend := InitJWTAuthenticationBackend()
10+
11+
token, err := jwt.ParseFromRequest(req, func(token *jwt.Token) (interface{}, error) {
12+
return authBackend.PublicKey, nil
13+
})
14+
15+
if err == nil && token.Valid {
16+
next(rw, req)
17+
} else {
18+
rw.WriteHeader(http.StatusUnauthorized)
19+
}
20+
}

provision/playbook.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
- name: Create a {{ application_name }} virtual machine via vagrant
2+
hosts: all
3+
sudo: yes
4+
sudo_user: root
5+
remote_user: vagrant
6+
vars:
7+
- update_apt_cache: yes
8+
vars_files:
9+
- vars.yml
10+
11+
roles:
12+
- base
13+
- postgresql
14+
- golang
15+
- redis

provision/roles/base/tasks/main.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
- name: Ensure OpenSSl and libssl are the latest versions
2+
apt: name={{ item }} update_cache=yes state=latest
3+
with_items:
4+
- openssl
5+
- libssl-dev
6+
- libssl-doc
7+
tags: packages
8+
9+
- name: Install base packages
10+
apt: name={{ item }} update_cache=yes force=yes state=installed
11+
with_items:
12+
- build-essential
13+
- ntp
14+
- htop
15+
- git
16+
- meld
17+
- mercurial
18+
tags: packages
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export PATH=$PATH:/usr/local/go/bin
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export GOPATH=$HOME/go
2+
export PATH=$GOPATH/bin:$PATH

provision/roles/golang/tasks/main.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
- name: Download the Go tarball
3+
get_url: url={{ go_download_location }}
4+
dest=/usr/local/src/{{ go_tarball }}
5+
sha256sum={{ go_tarball_checksum }}
6+
7+
- name: Register the current Go version (if any)
8+
command: /usr/local/go/bin/go version
9+
ignore_errors: yes
10+
register: go_version
11+
12+
- name: Extract the Go tarball if Go is not yet installed or if it is not the desired version
13+
command: tar -C /usr/local -xf /usr/local/src/{{ go_tarball }}
14+
when: go_version|failed or go_version.stdout != go_version_target
15+
16+
- name: Add the Go bin directory to the PATH environment variable for all users
17+
copy: src=go-bin.sh
18+
dest=/etc/profile.d
19+
20+
- name: Set GOPATH for all users
21+
copy: src=go-path.sh
22+
dest=/etc/profile.d
23+

provision/roles/golang/vars/main.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
go_tarball: "go1.4.2.linux-amd64.tar.gz"
2+
go_tarball_checksum: "141b8345932641483c2437bdbd65488a269282ac85f91170805c273f03dd223b"
3+
go_version_target: "go version go1.4.2 linux/amd64"
4+
5+
go_download_location: "http://golang.org/dl/{{ go_tarball }}"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
# handlers file for postgresql
3+
- name: restart postgresql
4+
service:
5+
name: postgresql
6+
state: restarted
7+
arguments: "{{ pg_version }}"
8+
sudo: true
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
- name: Install development headers
3+
apt: pkg="libpq-dev"
4+
sudo: yes
5+
when: pg_dev_headers == True
6+
tags:
7+
- postgresql
8+
9+
- name: Install PostgreSQL contribs
10+
apt: pkg="postgresql-contrib-{{ pg_version }}"
11+
sudo: yes
12+
when: pg_contrib
13+
tags:
14+
- postgresql

0 commit comments

Comments
 (0)