Skip to content

Commit

Permalink
Abstract out the code that creates the application name so it can be …
Browse files Browse the repository at this point in the history
…used in multiple places. Do a similar check in the javascript to get the cookie name.
  • Loading branch information
Chris Gilmer committed Feb 1, 2019
1 parent 15a33a8 commit 8f863db
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 25 deletions.
2 changes: 1 addition & 1 deletion cmd/webserver/main.go
Expand Up @@ -751,7 +751,7 @@ func main() {

// Session management and authentication middleware
noSessionTimeout := v.GetBool("no-session-timeout")
sessionCookieMiddleware := auth.SessionCookieMiddleware(zapLogger, clientAuthSecretKey, noSessionTimeout)
sessionCookieMiddleware := auth.SessionCookieMiddleware(zapLogger, clientAuthSecretKey, noSessionTimeout, myHostname, officeHostname, tspHostname)
maskedCSRFMiddleware := auth.MaskedCSRFMiddleware(zapLogger, noSessionTimeout)
appDetectionMiddleware := auth.DetectorMiddleware(zapLogger, myHostname, officeHostname, tspHostname)
userAuthMiddleware := authentication.UserAuthMiddleware(zapLogger)
Expand Down
39 changes: 24 additions & 15 deletions pkg/auth/app_detector.go
Expand Up @@ -5,18 +5,20 @@ import (
"strings"

"github.com/honeycombio/beeline-go"
"github.com/pkg/errors"
"go.uber.org/zap"
)

type application string
// Application describes the application name
type Application string

const (
// TspApp indicates tsp.move.mil
TspApp application = "TSP"
TspApp Application = "TSP"
// OfficeApp indicates office.move.mil
OfficeApp application = "OFFICE"
OfficeApp Application = "OFFICE"
// MyApp indicates my.move.mil
MyApp application = "MY"
MyApp Application = "MY"
)

// IsTspApp returns true iff the request is for the office.move.mil host
Expand All @@ -34,6 +36,19 @@ func (s *Session) IsMyApp() bool {
return s.ApplicationName == MyApp
}

// ApplicationName returns the application name given the hostname
func ApplicationName(hostname, myHostname, officeHostname, tspHostname string) (Application, error) {
var appName Application
if strings.EqualFold(hostname, myHostname) {
return MyApp, nil
} else if strings.EqualFold(hostname, officeHostname) {
return OfficeApp, nil
} else if strings.EqualFold(hostname, tspHostname) {
return TspApp, nil
}
return appName, errors.New("Bad hostname")
}

// DetectorMiddleware detects which application we are serving based on the hostname
func DetectorMiddleware(logger *zap.Logger, myHostname string, officeHostname string, tspHostname string) func(next http.Handler) http.Handler {
logger.Info("Creating host detector", zap.String("myHost", myHostname), zap.String("officeHost", officeHostname), zap.String("tspHost", tspHostname))
Expand All @@ -44,21 +59,15 @@ func DetectorMiddleware(logger *zap.Logger, myHostname string, officeHostname st

session := SessionFromRequestContext(r)

parts := strings.Split(r.Host, ":")
var appName application
if strings.EqualFold(parts[0], myHostname) {
appName = MyApp
} else if strings.EqualFold(parts[0], officeHostname) {
appName = OfficeApp
} else if strings.EqualFold(parts[0], tspHostname) {
appName = TspApp
} else {
// Split the hostname from the port
hostname := strings.Split(r.Host, ":")[0]
appName, err := ApplicationName(hostname, myHostname, officeHostname, tspHostname)
if err != nil {
logger.Error("Bad hostname", zap.String("hostname", r.Host))
http.Error(w, http.StatusText(400), http.StatusBadRequest)
return
}
session.ApplicationName = appName
session.Hostname = strings.ToLower(parts[0])
session.Hostname = strings.ToLower(hostname)

span.AddTraceField("auth.application_name", session.ApplicationName)
span.AddTraceField("auth.hostname", session.Hostname)
Expand Down
18 changes: 12 additions & 6 deletions pkg/auth/cookie.go
Expand Up @@ -60,10 +60,9 @@ func signTokenStringWithUserInfo(expiry time.Time, session *Session, secret stri
return ss, err
}

func sessionClaimsFromRequest(logger *zap.Logger, secret string, r *http.Request) (claims *SessionClaims, ok bool) {
func sessionClaimsFromRequest(logger *zap.Logger, secret string, appName Application, r *http.Request) (claims *SessionClaims, ok bool) {
// Name the cookie with the host name, use the same method as in the DetectorMiddleware
appName := strings.Split(strings.Split(r.Host, ":")[0], ".")[0]
cookieName := fmt.Sprintf("%s_%s", strings.ToLower(appName), UserSessionCookieName)
cookieName := fmt.Sprintf("%s_%s", strings.ToLower(string(appName)), UserSessionCookieName)
cookie, err := r.Cookie(cookieName)
if err != nil {
// No cookie set on client
Expand Down Expand Up @@ -127,7 +126,7 @@ func MaskedCSRFMiddleware(logger *zap.Logger, noSessionTimeout bool) func(next h
func WriteSessionCookie(w http.ResponseWriter, session *Session, secret string, noSessionTimeout bool, logger *zap.Logger) {

// Delete the cookie
cookieName := fmt.Sprintf("%s_%s", strings.Split(string(session.Hostname), "."), UserSessionCookieName)
cookieName := fmt.Sprintf("%s_%s", strings.ToLower(string(session.ApplicationName)), UserSessionCookieName)
cookie := http.Cookie{
Name: cookieName,
Value: "blank",
Expand Down Expand Up @@ -164,11 +163,18 @@ func WriteSessionCookie(w http.ResponseWriter, session *Session, secret string,
}

// SessionCookieMiddleware handle serializing and de-serializing the session between the user_session cookie and the request context
func SessionCookieMiddleware(logger *zap.Logger, secret string, noSessionTimeout bool) func(next http.Handler) http.Handler {
func SessionCookieMiddleware(logger *zap.Logger, secret string, noSessionTimeout bool, myHostname, officeHostname, tspHostname string) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
mw := func(w http.ResponseWriter, r *http.Request) {
session := Session{}
claims, ok := sessionClaimsFromRequest(logger, secret, r)

hostname := strings.Split(r.Host, ":")[0]
appName, err := ApplicationName(hostname, myHostname, officeHostname, tspHostname)
if err != nil {
logger.Error("Bad hostname", zap.String("hostname", r.Host))
http.Error(w, http.StatusText(400), http.StatusBadRequest)
}
claims, ok := sessionClaimsFromRequest(logger, secret, appName, r)
if ok {
session = claims.SessionValue
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/auth/session.go
Expand Up @@ -13,7 +13,7 @@ const sessionContextKey authSessionKey = "session"

// Session stores information about the currently logged in session
type Session struct {
ApplicationName application
ApplicationName Application
Hostname string
IDToken string
UserID uuid.UUID
Expand Down
5 changes: 3 additions & 2 deletions src/shared/User/ducks.js
@@ -1,7 +1,7 @@
import * as Cookies from 'js-cookie';
import * as decode from 'jwt-decode';
import * as helpers from 'shared/ReduxHelpers';
import { hostname } from 'shared/constants';
import { isMilmoveSite, isOfficeSite, isTspSite } from 'shared/constants';
import { GetLoggedInUser } from './api.js';
import { normalize } from 'normalizr';
import { pick } from 'lodash';
Expand Down Expand Up @@ -72,7 +72,8 @@ const loggedOutUser = {
};

function getUserInfo() {
const cookieName = hostname + '_session_token';
let cookiePrefix = (isMilmoveSite && 'my') || (isOfficeSite && 'office') || (isTspSite && 'tsp') || '';
const cookieName = cookiePrefix + '_session_token';
const cookie = Cookies.get(cookieName);
if (!cookie) return loggedOutUser;
const jwt = decode(cookie);
Expand Down
1 change: 1 addition & 0 deletions src/shared/constants.js
Expand Up @@ -11,6 +11,7 @@ export const ppmInfoPacket = '/downloads/ppm_info_sheet.pdf';
export const hhgInfoPacket = '/downloads/hhg_info_sheet.pdf';

export const hostname = window && window.location && window.location.hostname;
export const isMilmoveSite = hostname.startsWith('my') || hostname.startsWith('mil') || '';
export const isOfficeSite = hostname.startsWith('office') || '';
export const isTspSite = hostname.startsWith('tsp') || '';

Expand Down

0 comments on commit 8f863db

Please sign in to comment.