authentication.go 2.6 KB
Newer Older
Caro Axel's avatar
Caro Axel committed
1 2 3 4 5 6 7
package user

import (
	"io/ioutil"
	"regexp"
	"time"

8 9 10 11
	"dfss/dfssc/common"
	"dfss/dfssc/security"
	pb "dfss/dfssp/api"
	"errors"
Caro Axel's avatar
Caro Axel committed
12
	"golang.org/x/net/context"
13
	"google.golang.org/grpc"
Caro Axel's avatar
Caro Axel committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
)

// AuthManager handles the authentication of a user
type AuthManager struct {
	fileCA   string
	fileCert string
	addrPort string
	mail     string
	token    string
}

// NewAuthManager creates a new authentication manager with the given parameters
func NewAuthManager(fileCA, fileCert, addrPort, mail, token string) (*AuthManager, error) {
	m := &AuthManager{
		fileCA:   fileCA,
		fileCert: fileCert,
		addrPort: addrPort,
		mail:     mail,
		token:    token,
	}

	if err := m.checkValidParams(); err != nil {
		return nil, err
	}

	if err := m.checkFilePresence(); err != nil {
		return nil, err
	}

	return m, nil
}

func (m *AuthManager) checkValidParams() error {
	re, _ := regexp.Compile(`.+@.+\..+`)
	if b := re.MatchString(m.mail); !b {
		return errors.New("Provided mail is not valid")
	}

	return nil
}

func (m *AuthManager) checkFilePresence() error {
	if b := common.FileExists(m.fileCert); b {
		return errors.New("A certificate is already present at path " + m.fileCert)
	}

	if b := common.FileExists(m.fileCA); !b {
		return errors.New("You need the certificate of the platform at path " + m.fileCA)
	}

	data, err := security.GetCertificate(m.fileCA)
	if err != nil {
		return err
	}

	if time.Now().After(data.NotAfter) {
		return errors.New("Root certificate has expired")
	}

	return nil
}

// Authenticate performs the authentication request
// (ie connection to the platform grpc server, sending of the request, handling the response)
func (m *AuthManager) Authenticate() error {
	response, err := m.sendRequest()
	if err != nil {
		return err
	}

84
	return m.evaluateResponse(response)
Caro Axel's avatar
Caro Axel committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
}

// Creates the associated authentication request and sends it to the platform grpc server
func (m *AuthManager) sendRequest() (*pb.RegisteredUser, error) {
	client, err := connect(m.fileCA, m.addrPort)
	if err != nil {
		return nil, err
	}

	// gRPC request
	request := &pb.AuthRequest{
		Email: m.mail,
		Token: m.token,
	}

	// Stop the context if it takes too long for the platform to answer
101
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
Caro Axel's avatar
Caro Axel committed
102 103 104
	defer cancel()
	response, err := client.Auth(ctx, request)
	if err != nil {
105
		return nil, errors.New(grpc.ErrorDesc(err))
Caro Axel's avatar
Caro Axel committed
106 107 108 109 110 111 112 113 114
	}

	return response, nil
}

// Handle the platform grpc server's reponse to the authentication request
func (m *AuthManager) evaluateResponse(response *pb.RegisteredUser) error {
	cert := []byte(response.ClientCert)

115
	return ioutil.WriteFile(m.fileCert, cert, 0600)
Caro Axel's avatar
Caro Axel committed
116
}