github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/engine/login_oneshot.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package engine 5 6 import ( 7 "github.com/keybase/client/go/libkb" 8 keybase1 "github.com/keybase/client/go/protocol/keybase1" 9 ) 10 11 // "Oneshot login" is a login that works only once, say in an ephemeral 12 // context like a docker image. Bootstrap such a session with a paperkey, 13 // but the existence of the login won't hit the user's sigchain. 14 type LoginOneshot struct { 15 libkb.Contextified 16 arg keybase1.LoginOneshotArg 17 upak keybase1.UserPlusKeysV2 18 device *libkb.DeviceWithKeys 19 } 20 21 func NewLoginOneshot(g *libkb.GlobalContext, arg keybase1.LoginOneshotArg) *LoginOneshot { 22 return &LoginOneshot{ 23 Contextified: libkb.NewContextified(g), 24 arg: arg, 25 } 26 } 27 28 func (e *LoginOneshot) Name() string { 29 return "LoginOneshot" 30 } 31 32 func (e *LoginOneshot) Prereqs() Prereqs { 33 return Prereqs{} 34 } 35 36 func (e *LoginOneshot) RequiredUIs() []libkb.UIKind { return []libkb.UIKind{} } 37 func (e *LoginOneshot) SubConsumers() []libkb.UIConsumer { return []libkb.UIConsumer{} } 38 39 func (e *LoginOneshot) loadUser(m libkb.MetaContext) (err error) { 40 defer m.Trace("LoginOneshot#loadUser", &err)() 41 arg := libkb.NewLoadUserArgWithMetaContext(m).WithName(e.arg.Username) 42 var upak *keybase1.UserPlusKeysV2AllIncarnations 43 upak, _, err = m.G().GetUPAKLoader().LoadV2(arg) 44 if err != nil { 45 return err 46 } 47 e.upak = upak.Current 48 return nil 49 } 50 51 func (e *LoginOneshot) loadKey(m libkb.MetaContext) (err error) { 52 defer m.Trace("LoginOneshot#loadKey", &err)() 53 arg := PaperKeyGenArg{ 54 Passphrase: libkb.NewPaperKeyPhrase(e.arg.PaperKey), 55 SkipPush: true, 56 UID: e.upak.GetUID(), 57 } 58 eng := NewPaperKeyGen(e.G(), &arg) 59 err = RunEngine2(m, eng) 60 if err != nil { 61 return err 62 } 63 e.device = eng.DeviceWithKeys() 64 kid := e.device.SigningKey().GetKID() 65 deviceInfo := e.upak.FindDeviceKey(kid) 66 if deviceInfo == nil { 67 return libkb.NewNoDeviceError("no device found for paper key") 68 } 69 if deviceInfo.Base.Revocation != nil { 70 return libkb.NewKeyRevokedError(kid.String()) 71 } 72 e.device.SetDeviceInfo(deviceInfo.DeviceID, deviceInfo.DeviceDescription) 73 return nil 74 } 75 76 func (e *LoginOneshot) checkLogin(m libkb.MetaContext) (err error) { 77 defer m.Trace("LoginOneshot#checkLogin", &err)() 78 arg := libkb.NewRetryAPIArg("sesscheck") 79 arg.SessionType = libkb.APISessionTypeREQUIRED 80 _, err = m.G().API.Get(m, arg) 81 return err 82 } 83 84 func (e *LoginOneshot) makeLoginChanges(m libkb.MetaContext) (err error) { 85 defer m.Trace("LoginOneshot#makeLoginChanges", &err)() 86 nun := libkb.NewNormalizedUsername(e.upak.GetName()) 87 return m.SwitchUserToActiveOneshotDevice(e.upak.ToUserVersion(), nun, e.device) 88 } 89 90 func (e *LoginOneshot) commitLoginChanges(m libkb.MetaContext) (err error) { 91 defer m.Trace("LoginOneshot#commitLoginChanges", &err)() 92 m.G().NotifyRouter.HandleLogin(m.Ctx(), e.arg.Username) 93 m.G().CallLoginHooks(m) 94 return nil 95 } 96 97 func (e *LoginOneshot) rollbackLoginChanges(m libkb.MetaContext) (err error) { 98 defer m.Trace("LoginOneshot#rollbackLoginChanges", &err)() 99 return m.SwitchUserLoggedOut() 100 } 101 102 func (e *LoginOneshot) finish(m libkb.MetaContext) (err error) { 103 defer m.Trace("LoginOneshot#commit", &err)() 104 105 err = e.makeLoginChanges(m) 106 if err != nil { 107 return err 108 } 109 err = e.checkLogin(m) 110 if err == nil { 111 err = e.commitLoginChanges(m) 112 } else { 113 err = e.rollbackLoginChanges(m) 114 } 115 return err 116 } 117 118 func (e *LoginOneshot) checkPreconditions(m libkb.MetaContext) (err error) { 119 defer m.Trace("LoginOneshot#checkPreconditions", &err)() 120 if m.ActiveDevice().Valid() { 121 return libkb.LoggedInError{} 122 } 123 return nil 124 } 125 126 func (e *LoginOneshot) Run(m libkb.MetaContext) (err error) { 127 defer m.Trace("LoginOneshot#run", &err)() 128 129 if err = e.checkPreconditions(m); err != nil { 130 return err 131 } 132 133 if err = e.loadUser(m); err != nil { 134 return err 135 } 136 if err = e.loadKey(m); err != nil { 137 return err 138 } 139 err = e.finish(m) 140 return err 141 }