Skip to content

Commit

Permalink
Merge pull request #411 from MadAppGang/feature/access-to-generate-to…
Browse files Browse the repository at this point in the history
…ken-by-admin

Feature/generate impersonate token
  • Loading branch information
erudenko committed Jul 19, 2023
2 parents 9ea9a93 + b05312e commit 563f8c0
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
78 changes: 78 additions & 0 deletions web/api/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,3 +383,81 @@ func (ar *Router) loginFlow(app model.AppData, user model.User, requestedScopes
result.User = user
return result, nil
}

type impersonateData struct {
UserID string `json:"user_id" validate:"required"`
Scopes []string `json:"scopes,omitempty"`
}

// GetImpersonateToken returns a token that allows to impersonate a user.
func (ar *Router) GetImpersonateToken() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
locale := r.Header.Get("Accept-Language")

ld := impersonateData{}
if ar.MustParseJSON(w, r, &ld) != nil {
return
}

var err error
var user model.User

if len(ld.UserID) > 0 {
user, err = ar.server.Storages().User.UserByID(ld.UserID)
if err != nil {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorAPIRequestIncorrectLoginOrPassword)
return
}
} else {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorAPIRequestBodyInvalidError)
return
}

app := middleware.AppFromContext(r.Context())
if len(app.ID) == 0 {
ar.Error(w, locale, http.StatusBadRequest, l.ErrorAPIAPPNoAPPInContext)
return
}

// Authorize user if the app requires authorization.
azi := authorization.AuthzInfo{
App: app,
UserRole: user.AccessRole,
ResourceURI: r.RequestURI,
Method: r.Method,
}

if err := ar.Authorizer.Authorize(azi); err != nil {
ar.Error(w, locale, http.StatusForbidden, l.APIAccessDenied)
return
}

impersonateToken, err := ar.getImpersonateAccessToken(user, ld.Scopes, app)
if err != nil {
ar.Error(w, locale, http.StatusInternalServerError, l.ErrorAPILoginError, err)
return
}

ar.ServeJSON(w, locale, http.StatusOK, impersonateToken)
}
}

// getImpersonateAccessToken creates and returns access token for a user.
func (ar *Router) getImpersonateAccessToken(user model.User, scopes []string, app model.AppData) (string, error) {
tokenPayload, err := ar.getTokenPayloadForApp(app, user.ID)
if err != nil {
return "", err
}

token, err := ar.server.Services().Token.NewAccessToken(user, scopes, app, false, tokenPayload)
if err != nil {
return "", err
}

accessTokenString, err := ar.server.Services().Token.String(token)
if err != nil {
return "", err
}

return accessTokenString, nil
}
2 changes: 2 additions & 0 deletions web/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ func (ar *Router) buildAuthRoutes(middlewares *negroni.Negroni) http.Handler {
auth.Path("/invite").Handler(
ar.Token(model.TokenTypeAccess, nil)(ar.RequestInviteLink()),
).Methods(http.MethodPost)
auth.Path("/impersonate_token").Handler(
ar.GetImpersonateToken()).Methods(http.MethodPost)

auth.Path("/tfa/enable").Handler(
ar.Token(model.TokenTypeAccess, nil)(ar.EnableTFA()),
Expand Down

0 comments on commit 563f8c0

Please sign in to comment.