mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-06 21:53:09 -06:00
Replace ThreePID lookups with the new SSO lookups.
This commit is contained in:
parent
c3f7945284
commit
03cf5a5c08
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/dendrite/clientapi/userutil"
|
uapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -161,7 +161,7 @@ func (p *baseOIDCIdentityProvider) getOIDCAccessToken(ctx context.Context, req *
|
||||||
return resp.AccessToken, nil
|
return resp.AccessToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *baseOIDCIdentityProvider) getUserInfo(ctx context.Context, req *IdentityProviderRequest, oidcAccessToken string) (*userutil.ThirdPartyIdentifier, string, error) {
|
func (p *baseOIDCIdentityProvider) getUserInfo(ctx context.Context, req *IdentityProviderRequest, oidcAccessToken string) (ssoUser *UserIdentifier, suggestedUserID string, _ error) {
|
||||||
u, err := p.UserInfoURL.Execute(map[string]interface{}{
|
u, err := p.UserInfoURL.Execute(map[string]interface{}{
|
||||||
"Config": req.System,
|
"Config": req.System,
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
@ -187,34 +187,44 @@ func (p *baseOIDCIdentityProvider) getUserInfo(ctx context.Context, req *Identit
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var email string
|
if ctype != "application/json" {
|
||||||
var suggestedUserID string
|
|
||||||
switch ctype {
|
|
||||||
case "application/json":
|
|
||||||
body, err := ioutil.ReadAll(hresp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
emailRes := gjson.GetBytes(body, p.UserInfoEmailPath)
|
|
||||||
if !emailRes.Exists() {
|
|
||||||
return nil, "", fmt.Errorf("no email in user info response body")
|
|
||||||
}
|
|
||||||
email = emailRes.String()
|
|
||||||
|
|
||||||
// This is optional.
|
|
||||||
userIDRes := gjson.GetBytes(body, p.UserInfoSuggestedUserIDPath)
|
|
||||||
suggestedUserID = userIDRes.String()
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, "", fmt.Errorf("got unknown content type %q for user info", ctype)
|
return nil, "", fmt.Errorf("got unknown content type %q for user info", ctype)
|
||||||
}
|
}
|
||||||
|
|
||||||
if email == "" {
|
body, err := ioutil.ReadAll(hresp.Body)
|
||||||
return nil, "", fmt.Errorf("no email address in user info")
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &userutil.ThirdPartyIdentifier{Medium: "email", Address: email}, suggestedUserID, nil
|
issRes := gjson.GetBytes(body, "iss")
|
||||||
|
if !issRes.Exists() {
|
||||||
|
return nil, "", fmt.Errorf("no iss in user info response body")
|
||||||
|
}
|
||||||
|
iss := issRes.String()
|
||||||
|
|
||||||
|
subRes := gjson.GetBytes(body, "sub")
|
||||||
|
if !subRes.Exists() {
|
||||||
|
return nil, "", fmt.Errorf("no sub in user info response body")
|
||||||
|
}
|
||||||
|
sub := subRes.String()
|
||||||
|
|
||||||
|
if iss == "" {
|
||||||
|
return nil, "", fmt.Errorf("no iss in user info")
|
||||||
|
}
|
||||||
|
|
||||||
|
if sub == "" {
|
||||||
|
return nil, "", fmt.Errorf("no sub in user info")
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is optional.
|
||||||
|
userIDRes := gjson.GetBytes(body, p.UserInfoSuggestedUserIDPath)
|
||||||
|
suggestedUserID = userIDRes.String()
|
||||||
|
|
||||||
|
return &UserIdentifier{
|
||||||
|
Namespace: uapi.OIDCNamespace,
|
||||||
|
Issuer: iss,
|
||||||
|
Subject: sub,
|
||||||
|
}, suggestedUserID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type urlTemplate struct {
|
type urlTemplate struct {
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/userutil"
|
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
|
uapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IdentityProvider interface {
|
type IdentityProvider interface {
|
||||||
|
|
@ -37,7 +37,7 @@ type IdentityProviderRequest struct {
|
||||||
|
|
||||||
type CallbackResult struct {
|
type CallbackResult struct {
|
||||||
RedirectURL string
|
RedirectURL string
|
||||||
Identifier *userutil.ThirdPartyIdentifier
|
Identifier *UserIdentifier
|
||||||
SuggestedUserID string
|
SuggestedUserID string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,3 +55,8 @@ func GetIdentityProvider(t IdentityProviderType) IdentityProvider {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserIdentifier struct {
|
||||||
|
Namespace uapi.SSOIssuerNamespace
|
||||||
|
Issuer, Subject string
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,9 +165,9 @@ func SSOCallback(
|
||||||
return util.RedirectResponse(result.RedirectURL)
|
return util.RedirectResponse(result.RedirectURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := verifyThirdPartyUserIdentifier(ctx, userAPI, result.Identifier, cfg.Matrix.ServerName)
|
id, err := verifySSOUserIdentifier(ctx, userAPI, result.Identifier, cfg.Matrix.ServerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(ctx).WithError(err).WithField("identifier", result.Identifier.String()).Error("failed to find user")
|
util.GetLogger(ctx).WithError(err).WithField("identifier", result.Identifier).Error("failed to find user")
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusUnauthorized,
|
Code: http.StatusUnauthorized,
|
||||||
JSON: jsonerror.Forbidden("ID not associated with a local account"),
|
JSON: jsonerror.Forbidden("ID not associated with a local account"),
|
||||||
|
|
@ -176,7 +176,7 @@ func SSOCallback(
|
||||||
if id == nil {
|
if id == nil {
|
||||||
// The user doesn't exist.
|
// The user doesn't exist.
|
||||||
// TODO: let the user select a localpart and register an account.
|
// TODO: let the user select a localpart and register an account.
|
||||||
util.GetLogger(ctx).WithError(err).WithField("identifier", result.Identifier.String()).Error("failed to find user")
|
util.GetLogger(ctx).WithError(err).WithField("identifier", result.Identifier).Error("failed to find user")
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusNotImplemented,
|
Code: http.StatusNotImplemented,
|
||||||
JSON: jsonerror.Forbidden("SSO registration not implemented"),
|
JSON: jsonerror.Forbidden("SSO registration not implemented"),
|
||||||
|
|
@ -204,7 +204,7 @@ func SSOCallback(
|
||||||
type userAPIForSSO interface {
|
type userAPIForSSO interface {
|
||||||
uapi.LoginTokenInternalAPI
|
uapi.LoginTokenInternalAPI
|
||||||
|
|
||||||
QueryLocalpartForThreePID(ctx context.Context, req *uapi.QueryLocalpartForThreePIDRequest, res *uapi.QueryLocalpartForThreePIDResponse) error
|
QueryLocalpartForSSO(ctx context.Context, req *uapi.QueryLocalpartForSSORequest, res *uapi.QueryLocalpartForSSOResponse) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// getProvider looks up the given provider in the
|
// getProvider looks up the given provider in the
|
||||||
|
|
@ -254,16 +254,17 @@ func parseNonce(s string) (redirectURL *url.URL, _ error) {
|
||||||
return u, nil
|
return u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifyThirdPartyUserIdentifier resolves a ThirdPartyIdentifier to a
|
// verifySSOUserIdentifier resolves an sso.UserIdentifier to a
|
||||||
// UserIdentifier using the User API. Returns nil if there is no
|
// UserIdentifier using the User API. Returns nil if there is no
|
||||||
// associated user.
|
// associated user.
|
||||||
func verifyThirdPartyUserIdentifier(ctx context.Context, userAPI userAPIForSSO, id *userutil.ThirdPartyIdentifier, serverName gomatrixserverlib.ServerName) (*userutil.UserIdentifier, error) {
|
func verifySSOUserIdentifier(ctx context.Context, userAPI userAPIForSSO, id *sso.UserIdentifier, serverName gomatrixserverlib.ServerName) (*userutil.UserIdentifier, error) {
|
||||||
req := &uapi.QueryLocalpartForThreePIDRequest{
|
req := &uapi.QueryLocalpartForSSORequest{
|
||||||
ThreePID: id.Address,
|
Namespace: id.Namespace,
|
||||||
Medium: string(id.Medium),
|
Issuer: id.Issuer,
|
||||||
|
Subject: id.Subject,
|
||||||
}
|
}
|
||||||
var res uapi.QueryLocalpartForThreePIDResponse
|
var res uapi.QueryLocalpartForSSOResponse
|
||||||
if err := userAPI.QueryLocalpartForThreePID(ctx, req, &res); err != nil {
|
if err := userAPI.QueryLocalpartForSSO(ctx, req, &res); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if res.Localpart == "" {
|
if res.Localpart == "" {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue