oauth2.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package oauth2
  15. import (
  16. "context"
  17. "yunion.io/x/jsonutils"
  18. "yunion.io/x/log"
  19. "yunion.io/x/pkg/errors"
  20. api "yunion.io/x/onecloud/pkg/apis/identity"
  21. "yunion.io/x/onecloud/pkg/httperrors"
  22. "yunion.io/x/onecloud/pkg/keystone/driver"
  23. "yunion.io/x/onecloud/pkg/keystone/models"
  24. "yunion.io/x/onecloud/pkg/mcclient"
  25. )
  26. // OAuth2.0
  27. type SOAuth2Driver struct {
  28. driver.SBaseIdentityDriver
  29. oauth2Config *api.SOAuth2IdpConfigOptions
  30. isDebug bool
  31. }
  32. func NewOAuth2Driver(idpId, idpName, template, targetDomainId string, conf api.TConfigs) (driver.IIdentityBackend, error) {
  33. base, err := driver.NewBaseIdentityDriver(idpId, idpName, template, targetDomainId, conf)
  34. if err != nil {
  35. return nil, errors.Wrap(err, "NewBaseIdentityDriver")
  36. }
  37. drv := SOAuth2Driver{SBaseIdentityDriver: base}
  38. drv.SetVirtualObject(&drv)
  39. err = drv.prepareConfig()
  40. if err != nil {
  41. return nil, errors.Wrap(err, "prepareConfig")
  42. }
  43. return &drv, nil
  44. }
  45. func (self *SOAuth2Driver) prepareConfig() error {
  46. if self.oauth2Config == nil {
  47. confJson := jsonutils.Marshal(self.Config[api.IdentityDriverOAuth2])
  48. conf := api.SOAuth2IdpConfigOptions{}
  49. err := confJson.Unmarshal(&conf)
  50. if err != nil {
  51. return errors.Wrap(err, "json.Unmarshal")
  52. }
  53. log.Debugf("%s %s %#v", self.Config, confJson, self.oauth2Config)
  54. self.oauth2Config = &conf
  55. }
  56. return nil
  57. }
  58. func (self *SOAuth2Driver) GetSsoRedirectUri(ctx context.Context, callbackUrl, state string) (string, error) {
  59. factory := findDriverFactory(self.Template)
  60. if factory == nil {
  61. return "", errors.Wrapf(httperrors.ErrNotSupported, "template %s not supported", self.Template)
  62. }
  63. driver := factory.NewDriver(self.oauth2Config.AppId, self.oauth2Config.Secret)
  64. ctx = context.WithValue(ctx, "config", self.SBaseIdentityDriver.Config)
  65. return driver.GetSsoRedirectUri(ctx, callbackUrl, state)
  66. }
  67. func (self *SOAuth2Driver) Authenticate(ctx context.Context, ident mcclient.SAuthenticationIdentity) (*api.SUserExtended, error) {
  68. factory := findDriverFactory(self.Template)
  69. if factory == nil {
  70. return nil, errors.Wrapf(httperrors.ErrNotSupported, "template %s not supported", self.Template)
  71. }
  72. options := self.oauth2Config.SIdpAttributeOptions
  73. options.Update(factory.IdpAttributeOptions())
  74. driver := factory.NewDriver(self.oauth2Config.AppId, self.oauth2Config.Secret)
  75. ctx = context.WithValue(ctx, "config", self.SBaseIdentityDriver.Config)
  76. attrs, err := driver.Authenticate(ctx, ident.OAuth2.Code)
  77. if err != nil {
  78. return nil, errors.Wrapf(err, "driver %s Authenticate", self.Template)
  79. }
  80. var domainId, domainName, usrId, usrName string
  81. if v, ok := attrs[options.DomainIdAttribute]; ok && len(v) > 0 {
  82. domainId = v[0]
  83. }
  84. if v, ok := attrs[options.DomainNameAttribute]; ok && len(v) > 0 {
  85. domainName = v[0]
  86. }
  87. if v, ok := attrs[options.UserIdAttribute]; ok && len(v) > 0 {
  88. usrId = v[0]
  89. }
  90. if v, ok := attrs[options.UserNameAttribute]; ok && len(v) > 0 {
  91. usrName = v[0]
  92. }
  93. idp, err := models.IdentityProviderManager.FetchIdentityProviderById(self.IdpId)
  94. if err != nil {
  95. return nil, errors.Wrap(err, "self.GetIdentityProvider")
  96. }
  97. domain, usr, err := idp.SyncOrCreateDomainAndUser(ctx, domainId, domainName, usrId, usrName)
  98. if err != nil {
  99. return nil, errors.Wrap(err, "idp.SyncOrCreateDomainAndUser")
  100. }
  101. extUser, err := models.UserManager.FetchUserExtended(usr.Id, "", "", "")
  102. if err != nil {
  103. return nil, errors.Wrap(err, "models.UserManager.FetchUserExtended")
  104. }
  105. idp.TryUserJoinProject(options, ctx, usr, domain.Id, attrs)
  106. extUser.AuditIds = []string{ident.OAuth2.Code}
  107. return extUser, nil
  108. }
  109. func (self *SOAuth2Driver) Sync(ctx context.Context) error {
  110. factory := findDriverFactory(self.Template)
  111. if factory == nil {
  112. return nil
  113. }
  114. if driver, isOk := factory.NewDriver(self.oauth2Config.AppId, self.oauth2Config.Secret).(IOAuth2Synchronizer); isOk {
  115. ctx = context.WithValue(ctx, "config", self.SBaseIdentityDriver.Config)
  116. return driver.Sync(ctx, self.IdpId)
  117. }
  118. return nil
  119. }
  120. func (self *SOAuth2Driver) Probe(ctx context.Context) error {
  121. return nil
  122. }