tchapgouv / tchap-ios

A Matrix client for iOS
https://apps.apple.com/fr/app/tchap/id1446253779
GNU Affero General Public License v3.0
60 stars 17 forks source link

Etude : OpenID dans Tchap iOS #965

Open NicolasBuquet opened 9 months ago

NicolasBuquet commented 9 months ago

Analyser l'usage de OpenID Connect dans le code de Tchap :

NicolasBuquet commented 9 months ago

Dans le Matrix SDK

Classe MXIdentityServerRestClient :

#pragma mark Authentication

/**
 Register with an identity server using the OpenID token from the user's homeserver (v2 API).

 @param openIdToken The OpenID token from an homeserver.
 @param success A block object called when the operation succeeds. It provides the user access token for the identity server.
 @param failure A block object called when the operation fails.

 @return a MXHTTPOperation instance.
 */
- (MXHTTPOperation*)registerWithOpenIdToken:(MXOpenIdToken*)openIdToken
                                    success:(void (^)(NSString *accessToken))success
                                    failure:(void (^)(NSError *error))failure;

/**
 Gets information about the token's owner, such as the user ID for which it belongs.

 @param success A block object called when the operation succeeds. It provides the user ID which was represented in the OpenID object provided to /register.
 @param failure A block object called when the operation fails.

 @return a MXHTTPOperation instance.
 */
- (MXHTTPOperation*)accountWithSuccess:(void (^)(NSString *userId))success
                               failure:(void (^)(NSError *error))failure;

Path appelé sur le back-end : _matrix/identity/v2/account/register

Classe MXIdentityService:

La méthode suivante nécessite un openID token pour demander un nouvel access token.

- (MXHTTPOperation*)renewAccessTokenWithSuccess:(void (^)(NSString*))success failure:(void (^)(NSError *))failure
{
    if (!self.homeserverRestClient)
    {
        NSError *error = [NSError errorWithDomain:@"MXIdentityService" code:0 userInfo:nil];
        failure(error);
        return nil;
    }

    MXHTTPOperation *operation;

    MXWeakify(self);

    operation = [self.homeserverRestClient openIdToken:^(MXOpenIdToken *tokenObject) {

        MXStrongifyAndReturnIfNil(self);

        MXHTTPOperation *operation2 = [self.restClient registerWithOpenIdToken:tokenObject success:^(NSString * _Nonnull accessToken) {

            success(accessToken);

        } failure:^(NSError * _Nonnull error) {
            failure(error);
        }];

        // Mutate MXHTTPOperation so that the user can cancel this new operation
        [operation mutateTo:operation2];

    } failure:^(NSError *error) {
        failure(error);
    }];

    return operation;
}

Classe MXJSONModels :

Déclare l'interface MXOpenIdToken:

/**
 `MXOpenIdToken` represents the response to the `openIdToken` request.
 */
@interface MXOpenIdToken : MXJSONModel

/**
 The token type.
 */
@property (nonatomic) NSString *tokenType;

/**
 The homeserver name.
 */
@property (nonatomic) NSString *matrixServerName;

/**
 The generated access token.
 */
@property (nonatomic) NSString *accessToken;

/**
 The valid period in seconds of this token.
 */
@property (nonatomic) uint64_t expiresIn;

@end

Classe MXRestClient :

/**
 Gets a bearer token from the homeserver that the user can
 present to a third party in order to prove their ownership
 of the Matrix account they are logged into.

 @param success A block object called when the operation succeeds.
 @param failure A block object called when the operation fails.

 @return a MXHTTPOperation instance.
 */
- (MXHTTPOperation*)openIdToken:(void (^)(MXOpenIdToken *tokenObject))success
                        failure:(void (^)(NSError *error))failure;

Path appelé sur le back-end : _matrix/client/unstable/user/<user-id>/openid/request_token

NicolasBuquet commented 9 months ago

L'obtention de l'openID token semble passer par l'intégration d'un service tiers par la classe IntegrationManagerViewController :

- (WidgetManagerConfig*)createWidgetManagerConfigForUser:(NSString*)userId
{
    WidgetManagerConfig *config;

    MXSession *session = [self matrixSessionForUser:userId];

    // Find the integrations settings for the user

    // First, look at matrix account
    // TODO in another user story

    // Then, try to the homeserver configuration
    MXWellknownIntegrationsManager *integrationsManager = session.homeserverWellknown.integrations.managers.firstObject;
    if (integrationsManager)
    {
        config = [[WidgetManagerConfig alloc] initWithApiUrl:integrationsManager.apiUrl uiUrl:integrationsManager.uiUrl];
    }
    else
    {
        // Fallback on app settings
        config = [self createWidgetManagerConfigWithAppSettings];
    }

    return config;
}

- (WidgetManagerConfig*)createWidgetManagerConfigWithAppSettings
{
    return [[WidgetManagerConfig alloc] initWithApiUrl:BuildSettings.integrationsRestApiUrlString
                                                 uiUrl:BuildSettings.integrationsUiUrlString];
}
NicolasBuquet commented 9 months ago

L'usage de OpenID dans Matrix est basé sur la MSC1961 : https://github.com/matrix-org/matrix-spec-proposals/blob/old_master/proposals/1961-integrations-auth.md

The Matrix spec proposal pull request : https://github.com/matrix-org/matrix-spec-proposals/pull/1961

https://github.com/matrix-org/matrix-doc/pull/2140 defines a new v2 API for Identity Servers and uses OpenID authentication as defined in https://github.com/matrix-org/matrix-doc/pull/1961.