mirror of
https://github.com/hoernschen/dendrite.git
synced 2024-12-27 07:28:27 +00:00
Check for AS user before real user
This commit is contained in:
parent
2fb2f7ca7b
commit
1fd2686bac
1 changed files with 69 additions and 43 deletions
|
@ -65,14 +65,33 @@ type Data struct {
|
||||||
func VerifyUserFromRequest(
|
func VerifyUserFromRequest(
|
||||||
req *http.Request, data Data,
|
req *http.Request, data Data,
|
||||||
) (*authtypes.Device, *util.JSONResponse) {
|
) (*authtypes.Device, *util.JSONResponse) {
|
||||||
// Try to find local user from device database
|
// Check to see if this is an application service user
|
||||||
dev, devErr := verifyAccessToken(req, data.DeviceDB)
|
dev, err := verifyApplicationServiceUser(req, data)
|
||||||
if devErr == nil {
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if dev != nil {
|
||||||
return dev, nil
|
return dev, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to find local user from device database
|
||||||
|
dev, err = verifyAccessToken(req, data.DeviceDB)
|
||||||
|
if err == nil {
|
||||||
|
return dev, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, &util.JSONResponse{
|
||||||
|
Code: http.StatusUnauthorized,
|
||||||
|
JSON: jsonerror.UnknownToken("Unrecognized access token"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyApplicationServiceUser attempts to retrieve a userID given a request
|
||||||
|
// originating from an application service
|
||||||
|
func verifyApplicationServiceUser(
|
||||||
|
req *http.Request, data Data,
|
||||||
|
) (*authtypes.Device, *util.JSONResponse) {
|
||||||
// Try to find the Application Service user
|
// Try to find the Application Service user
|
||||||
token, err := extractAccessToken(req)
|
token, err := extractApplicationServiceAccessToken(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &util.JSONResponse{
|
return nil, &util.JSONResponse{
|
||||||
Code: http.StatusUnauthorized,
|
Code: http.StatusUnauthorized,
|
||||||
|
@ -89,6 +108,7 @@ func VerifyUserFromRequest(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userID := req.URL.Query().Get("user_id")
|
||||||
if appService != nil {
|
if appService != nil {
|
||||||
// Create a dummy device for AS user
|
// Create a dummy device for AS user
|
||||||
dev := authtypes.Device{
|
dev := authtypes.Device{
|
||||||
|
@ -98,7 +118,8 @@ func VerifyUserFromRequest(
|
||||||
AccessToken: token,
|
AccessToken: token,
|
||||||
}
|
}
|
||||||
|
|
||||||
userID := req.URL.Query().Get("user_id")
|
// Check for user masquerading
|
||||||
|
if userID != "" {
|
||||||
localpart, err := userutil.ParseUsernameParam(userID, nil)
|
localpart, err := userutil.ParseUsernameParam(userID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &util.JSONResponse{
|
return nil, &util.JSONResponse{
|
||||||
|
@ -122,23 +143,22 @@ func VerifyUserFromRequest(
|
||||||
JSON: jsonerror.Forbidden("Application service has not registered this user"),
|
JSON: jsonerror.Forbidden("Application service has not registered this user"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
// AS is not masquerading as any user, so use AS's sender_localpart
|
// AS is not masquerading as any user, so use AS's sender_localpart
|
||||||
dev.UserID = appService.SenderLocalpart
|
dev.UserID = appService.SenderLocalpart
|
||||||
|
}
|
||||||
return &dev, nil
|
return &dev, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, &util.JSONResponse{
|
// Application service was not found with this token
|
||||||
Code: http.StatusUnauthorized,
|
return nil, nil
|
||||||
JSON: jsonerror.UnknownToken("Unrecognized access token"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifyAccessToken verifies that an access token was supplied in the given HTTP request
|
// verifyAccessToken verifies that an access token was supplied in the given HTTP request
|
||||||
// and returns the device it corresponds to. Returns resErr (an error response which can be
|
// and returns the device it corresponds to. Returns resErr (an error response which can be
|
||||||
// sent to the client) if the token is invalid or there was a problem querying the database.
|
// sent to the client) if the token is invalid or there was a problem querying the database.
|
||||||
func verifyAccessToken(req *http.Request, deviceDB DeviceDatabase) (device *authtypes.Device, resErr *util.JSONResponse) {
|
func verifyAccessToken(req *http.Request, deviceDB DeviceDatabase) (device *authtypes.Device, resErr *util.JSONResponse) {
|
||||||
token, err := extractAccessToken(req)
|
token, err := extractUserAccessToken(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resErr = &util.JSONResponse{
|
resErr = &util.JSONResponse{
|
||||||
Code: http.StatusUnauthorized,
|
Code: http.StatusUnauthorized,
|
||||||
|
@ -172,20 +192,26 @@ func GenerateAccessToken() (string, error) {
|
||||||
return base64.RawURLEncoding.EncodeToString(b), nil
|
return base64.RawURLEncoding.EncodeToString(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractAccessToken from a request, or return an error detailing what went wrong. The
|
// extractApplicationServiceAccessToken retreives an access token from a request
|
||||||
// error message MUST be human-readable and comprehensible to the client.
|
// originating from an application service
|
||||||
func extractAccessToken(req *http.Request) (string, error) {
|
func extractApplicationServiceAccessToken(req *http.Request) (string, error) {
|
||||||
// cf https://github.com/matrix-org/synapse/blob/v0.19.2/synapse/api/auth.py#L631
|
|
||||||
authBearer := req.Header.Get("Authorization")
|
authBearer := req.Header.Get("Authorization")
|
||||||
queryToken := req.URL.Query().Get("access_token")
|
token := req.URL.Query().Get("access_token")
|
||||||
if authBearer != "" && queryToken != "" {
|
if authBearer != "" && token != "" {
|
||||||
return "", fmt.Errorf("mixing Authorization headers and access_token query parameters")
|
return "", fmt.Errorf("mixing Authorization headers and access_token query parameters")
|
||||||
}
|
}
|
||||||
|
if token != "" {
|
||||||
if queryToken != "" {
|
return token, nil
|
||||||
return queryToken, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("missing access token")
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractUserAccessToken retreives an access token from a request originating
|
||||||
|
// from a non-application service
|
||||||
|
func extractUserAccessToken(req *http.Request) (string, error) {
|
||||||
|
authBearer := req.Header.Get("Authorization")
|
||||||
|
|
||||||
if authBearer != "" {
|
if authBearer != "" {
|
||||||
parts := strings.SplitN(authBearer, " ", 2)
|
parts := strings.SplitN(authBearer, " ", 2)
|
||||||
if len(parts) != 2 || parts[0] != "Bearer" {
|
if len(parts) != 2 || parts[0] != "Bearer" {
|
||||||
|
|
Loading…
Reference in a new issue