Skip to content

Commit

Permalink
Implement Pre-authenticated URL
Browse files Browse the repository at this point in the history
ref DEV-1402
  • Loading branch information
louischan-oursky committed Jul 10, 2024
2 parents 4095d81 + 2520e37 commit 26a809e
Show file tree
Hide file tree
Showing 84 changed files with 3,728 additions and 736 deletions.
1 change: 1 addition & 0 deletions cmd/authgear/background/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions e2e/cmd/e2e/pkg/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions pkg/admin/facade/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ type OAuthTokenService interface {
client *config.OAuthClientConfig,
opts handler.IssueOfflineGrantOptions,
resp protocol.TokenResponse,
) (*oauth.OfflineGrant, error)
) (offlineGrant *oauth.OfflineGrant, tokenHash string, err error)
IssueAccessGrant(
client *config.OAuthClientConfig,
scopes []string,
authzID string,
userID string,
sessionID string,
sessionKind oauth.GrantSessionKind,
refreshTokenHash string,
resp protocol.TokenResponse,
) error
}
Expand All @@ -49,10 +50,10 @@ type OAuthFacade struct {
OAuthClientResolver OAuthClientResolver
}

func (f *OAuthFacade) CreateSession(clientID string, userID string) (session.Session, protocol.TokenResponse, error) {
func (f *OAuthFacade) CreateSession(clientID string, userID string) (session.ListableSession, protocol.TokenResponse, error) {
scopes := []string{
"openid",
"offline_access",
oauth.OfflineAccess,
oauth.FullAccessScope,
}
authenticationInfo := authenticationinfo.T{
Expand Down Expand Up @@ -92,7 +93,7 @@ func (f *OAuthFacade) CreateSession(clientID string, userID string) (session.Ses
}

resp := protocol.TokenResponse{}
offlineGrant, err := f.Tokens.IssueOfflineGrant(client, offlineGrantOpts, resp)
offlineGrant, tokenHash, err := f.Tokens.IssueOfflineGrant(client, offlineGrantOpts, resp)
if err != nil {
return nil, nil, err
}
Expand All @@ -104,6 +105,7 @@ func (f *OAuthFacade) CreateSession(clientID string, userID string) (session.Ses
authz.UserID,
offlineGrant.ID,
oauth.GrantSessionKindOffline,
tokenHash,
resp,
)
if err != nil {
Expand Down
12 changes: 6 additions & 6 deletions pkg/admin/facade/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ import (
)

type SessionManager interface {
List(userID string) ([]session.Session, error)
Get(id string) (session.Session, error)
RevokeWithEvent(session session.Session, isTermination bool, isAdminAPI bool) error
TerminateAllExcept(userID string, currentSession session.Session, isAdminAPI bool) error
List(userID string) ([]session.ListableSession, error)
Get(id string) (session.ListableSession, error)
RevokeWithEvent(session session.SessionBase, isTermination bool, isAdminAPI bool) error
TerminateAllExcept(userID string, currentSession session.ResolvedSession, isAdminAPI bool) error
}

type SessionFacade struct {
Sessions SessionManager
}

func (f *SessionFacade) List(userID string) ([]session.Session, error) {
func (f *SessionFacade) List(userID string) ([]session.ListableSession, error) {
return f.Sessions.List(userID)
}

func (f *SessionFacade) Get(id string) (session.Session, error) {
func (f *SessionFacade) Get(id string) (session.ListableSession, error) {
return f.Sessions.Get(id)
}

Expand Down
8 changes: 4 additions & 4 deletions pkg/admin/graphql/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ type UserProfileFacade interface {
}

type SessionFacade interface {
List(userID string) ([]session.Session, error)
Get(id string) (session.Session, error)
List(userID string) ([]session.ListableSession, error)
Get(id string) (session.ListableSession, error)
Revoke(id string) error
RevokeAll(userID string) error
}
Expand All @@ -162,11 +162,11 @@ type AuthorizationFacade interface {
}

type OAuthFacade interface {
CreateSession(clientID string, userID string) (session.Session, protocol.TokenResponse, error)
CreateSession(clientID string, userID string) (session.ListableSession, protocol.TokenResponse, error)
}

type SessionListingService interface {
FilterForDisplay(sessions []session.Session, currentSession session.Session) ([]*sessionlisting.Session, error)
FilterForDisplay(sessions []session.ListableSession, currentSession session.ResolvedSession) ([]*sessionlisting.Session, error)
}

type OTPCodeService interface {
Expand Down
30 changes: 24 additions & 6 deletions pkg/admin/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/api/model/claims.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const (
ClaimEmail ClaimName = "email"
ClaimPhoneNumber ClaimName = "phone_number"
ClaimPreferredUsername ClaimName = "preferred_username"
ClaimDeviceSecretHash ClaimName = "ds_hash"
ClaimAuthgearRoles ClaimName = "https://authgear.com/claims/user/roles"
ClaimKeyID ClaimName = "https://authgear.com/claims/user/key_id"
ClaimUserIsAnonymous ClaimName = "https://authgear.com/claims/user/is_anonymous"
Expand Down
2 changes: 1 addition & 1 deletion pkg/auth/handler/oauth/end_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func NewEndSessionHandlerLogger(lf *log.Factory) EndSessionHandlerLogger {
}

type ProtocolEndSessionHandler interface {
Handle(session.Session, protocol.EndSessionRequest, *http.Request, http.ResponseWriter) error
Handle(session.ResolvedSession, protocol.EndSessionRequest, *http.Request, http.ResponseWriter) error
}

type EndSessionHandler struct {
Expand Down
19 changes: 12 additions & 7 deletions pkg/auth/handler/webapp/authflowv2/select_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/authgear/authgear-server/pkg/lib/authn/authenticationinfo"
"github.com/authgear/authgear-server/pkg/lib/authn/identity"
"github.com/authgear/authgear-server/pkg/lib/config"
"github.com/authgear/authgear-server/pkg/lib/oauth"
"github.com/authgear/authgear-server/pkg/lib/session"
"github.com/authgear/authgear-server/pkg/util/accesscontrol"
"github.com/authgear/authgear-server/pkg/util/httproute"
Expand Down Expand Up @@ -100,7 +101,7 @@ func (h *AuthflowV2SelectAccountHandler) ServeHTTP(w http.ResponseWriter, r *htt
return
}

idpSession := session.GetSession(r.Context())
session := session.GetSession(r.Context())
webSession := webapp.GetSession(r.Context())

oauthSessionID := ""
Expand All @@ -121,7 +122,11 @@ func (h *AuthflowV2SelectAccountHandler) ServeHTTP(w http.ResponseWriter, r *htt

// When x_suppress_idp_session_cookie is true, ignore IDP session cookie.
if suppressIDPSessionCookie {
idpSession = nil
session = nil
}
// Ignore any session that is not allow to be used here
if !oauth.ContainsAllScopes(oauth.SessionScopes(session), []string{oauth.PreAuthenticatedURLScope}) {
session = nil
}

continueWithCurrentAccount := func() error {
Expand All @@ -140,8 +145,8 @@ func (h *AuthflowV2SelectAccountHandler) ServeHTTP(w http.ResponseWriter, r *htt
}

// Write authentication info cookie
if idpSession != nil {
info := idpSession.GetAuthenticationInfo()
if session != nil {
info := session.GetAuthenticationInfo()
entry := authenticationinfo.NewEntry(info, oauthSessionID)
err := h.AuthenticationInfoService.Save(entry)
if err != nil {
Expand Down Expand Up @@ -207,7 +212,7 @@ func (h *AuthflowV2SelectAccountHandler) ServeHTTP(w http.ResponseWriter, r *htt
if userIDHint != "" {
if loginPrompt && canUseIntentReauthenticate {
gotoReauth()
} else if !loginPrompt && idpSession != nil && idpSession.GetAuthenticationInfo().UserID == userIDHint {
} else if !loginPrompt && session != nil && session.GetAuthenticationInfo().UserID == userIDHint {
// Continue without user interaction
// 1. UserIDHint present
// 2. IDP session present and the same as UserIDHint
Expand Down Expand Up @@ -236,12 +241,12 @@ func (h *AuthflowV2SelectAccountHandler) ServeHTTP(w http.ResponseWriter, r *htt
}

fromAuthzEndpoint := oauthSessionID != ""
if !fromAuthzEndpoint || idpSession == nil || loginPrompt {
if !fromAuthzEndpoint || session == nil || loginPrompt {
gotoSignupOrLogin()
return nil
}

data, err := h.GetData(r, w, idpSession.GetAuthenticationInfo().UserID)
data, err := h.GetData(r, w, session.GetAuthenticationInfo().UserID)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/auth/handler/webapp/logout.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func ConfigureLogoutRoute(route httproute.Route) httproute.Route {
}

type LogoutSessionManager interface {
Logout(session.Session, http.ResponseWriter) error
Logout(session.ResolvedSession, http.ResponseWriter) error
}

type LogoutHandler struct {
Expand Down
14 changes: 7 additions & 7 deletions pkg/auth/handler/webapp/select_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (h *SelectAccountHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
return
}

idpSession := session.GetSession(r.Context())
session := session.GetSession(r.Context())
webSession := webapp.GetSession(r.Context())

oauthSessionID := ""
Expand All @@ -120,7 +120,7 @@ func (h *SelectAccountHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

// When x_suppress_idp_session_cookie is true, ignore IDP session cookie.
if suppressIDPSessionCookie {
idpSession = nil
session = nil
}

continueWithCurrentAccount := func() error {
Expand All @@ -139,8 +139,8 @@ func (h *SelectAccountHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
}

// Write authentication info cookie
if idpSession != nil {
info := idpSession.GetAuthenticationInfo()
if session != nil {
info := session.GetAuthenticationInfo()
entry := authenticationinfo.NewEntry(info, oauthSessionID)
err := h.AuthenticationInfoService.Save(entry)
if err != nil {
Expand Down Expand Up @@ -206,7 +206,7 @@ func (h *SelectAccountHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
if userIDHint != "" {
if loginPrompt && canUseIntentReauthenticate {
gotoReauth()
} else if !loginPrompt && idpSession != nil && idpSession.GetAuthenticationInfo().UserID == userIDHint {
} else if !loginPrompt && session != nil && session.GetAuthenticationInfo().UserID == userIDHint {
// Continue without user interaction
// 1. UserIDHint present
// 2. IDP session present and the same as UserIDHint
Expand Down Expand Up @@ -235,12 +235,12 @@ func (h *SelectAccountHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
}

fromAuthzEndpoint := oauthSessionID != ""
if !fromAuthzEndpoint || idpSession == nil || loginPrompt {
if !fromAuthzEndpoint || session == nil || loginPrompt {
gotoSignupOrLogin()
return nil
}

data, err := h.GetData(r, w, idpSession.GetAuthenticationInfo().UserID)
data, err := h.GetData(r, w, session.GetAuthenticationInfo().UserID)
if err != nil {
return err
}
Expand Down
10 changes: 5 additions & 5 deletions pkg/auth/handler/webapp/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ type SettingsVerificationService interface {
}

type SettingsSessionManager interface {
List(userID string) ([]session.Session, error)
Get(id string) (session.Session, error)
RevokeWithEvent(s session.Session, isTermination bool, isAdminAPI bool) error
TerminateAllExcept(userID string, currentSession session.Session, isAdminAPI bool) error
List(userID string) ([]session.ListableSession, error)
Get(id string) (session.ListableSession, error)
RevokeWithEvent(s session.SessionBase, isTermination bool, isAdminAPI bool) error
TerminateAllExcept(userID string, currentSession session.ResolvedSession, isAdminAPI bool) error
}

type SettingsAuthorizationService interface {
Expand All @@ -63,7 +63,7 @@ type SettingsAuthorizationService interface {
}

type SettingsSessionListingService interface {
FilterForDisplay(sessions []session.Session, currentSession session.Session) ([]*sessionlisting.Session, error)
FilterForDisplay(sessions []session.ListableSession, currentSession session.ResolvedSession) ([]*sessionlisting.Session, error)
}

type SettingsHandler struct {
Expand Down
2 changes: 1 addition & 1 deletion pkg/auth/handler/webapp/settings_sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type SettingsSessionsHandler struct {
SessionListing SettingsSessionListingService
}

func (h *SettingsSessionsHandler) GetData(r *http.Request, rw http.ResponseWriter, s session.Session) (map[string]interface{}, error) {
func (h *SettingsSessionsHandler) GetData(r *http.Request, rw http.ResponseWriter, s session.ResolvedSession) (map[string]interface{}, error) {
data := map[string]interface{}{}
baseViewModel := h.BaseViewModel.ViewModel(r, rw)
viewmodels.Embed(data, baseViewModel)
Expand Down
2 changes: 1 addition & 1 deletion pkg/auth/handler/webapp/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ type TesterHandler struct {
}

var TesterScopes = []string{
"openid", "offline_access", oauth.FullAccessScope,
"openid", oauth.OfflineAccess, oauth.FullAccessScope,
}

type TesterState struct {
Expand Down
Loading

0 comments on commit 26a809e

Please sign in to comment.