Gestion des accès aux APIs REST de WSO2 IS — Opérationnelle [2/2]

Gregory EVE
Smile with WSO2
Published in
4 min readNov 5, 2020

WSO2 migre progressivement l’ensemble des web services SOAP d’administration de ses produits vers des APIs REST JSON. Nous allons nous pencher sur comment le contrôle d’accès à ces APIs est réalisés.

Cette série, “Gestion des accès aux APIs REST de WSO2 IS” est en 2 parties :

1. Technique

2. Opérationnelle

Gestion des permissions utilisateur

Nous avons vu la technique mais maintenant il est temps de se pencher sur l’opérationnel.

Permissions pour un utilisateur final

Si les APIs sont appelés par un utilisateur, directement ou indirectement, il vous suffit de lui donner un rôle avec les bonnes permissions.

Si vos appels sont faits avec Oauth 2 n’oubliez pas de préciser les bons scopes à la demande du token ou si vous êtes fainéant utiliser le scope magique “SYSTEM” qui vous fournira un token avec tous les scopes que l’utilisateur peut avoir.

Permissions pour une application

Dans certains cas vous souhaitez accéder aux APIs via uniquement un client applicatif.

  • via une authentification mutuelle SSL ou secret client il n’y a aucun contrôle de permissions.
  • via oauth2 et le grant type client credentials les permissions dépendent de l’application Oauth2 que vous avez déclaré et plus précisément de son propriétaire

Exemple avec Oauth2 :

Nous souhaitons déporter un formulaire d’inscription dans une autre application et ne donner à celle-ci que les droits de création de compte.
Nous allons faire appel à l’API SCIM 2.0 et plus particulièrement à POST /scim2/users qui nécessite la permission /permission/admin/manage/identity/usermgt/create et le scope internal_user_mgt_create

curl -X POST "https://is.docs.wso2.com/t/{tenant-domain}/scim2/Users" -H "accept: application/scim+json" -H "Content-Type: application/scim+json" -d "{ \"schemas\": [], \"name\": { \"firstName\": \"Kim\", \"lastName\": \"Berry\" }, \"userName\": \"kim\", \"password\": \"abc123\", \"emails\": [ [ { \"type\": \"home\", \"value\": \"kim@gmail.com\", \"primary\": true }, { \"type\": \"work\", \"value\": \"kim@wso2,com\" } ] ], \"EnterpriseUser\": { \"employeeNumber\": \"1234A\", \"manager\": { \"value\": \"Taylor\" } }}"

La première étape consiste donc à déclarer notre application Oauth 2 au sein de WSO2 Identity Server en activant le grant type “code”:

Avec les identifiants applicatifs nous générons un token avec le scope SYSTEM:

curl -k -u QcuDDF5BiHdaF0fAJf_QryVRhaga:aNjl77GZqaf6iP_d0lGP96AZsksa -k -d "grant_type=client_credentials&scope=SYSTEM" -H "Content-Type:application/x-www-form-urlencoded" https://localhost:9443/oauth2/token
{"access_token":"40281610-821e-34ad-9592-513f6c372ff1","scope":"internal_add_attachements internal_add_bpel internal_add_extensions internal_add_module internal_add_services internal_add_webapp internal_app_template_create internal_app_template_delete internal_app_template_update internal_app_template_view internal_application_mgt_create internal_application_mgt_delete internal_application_mgt_update internal_application_mgt_view internal_auth_seq_create internal_auth_seq_delete internal_auth_seq_update internal_auth_seq_view internal_bpel_instances internal_bpel_packages internal_bpel_proceses internal_challenge_questions_create internal_challenge_questions_delete internal_challenge_questions_update internal_challenge_questions_view internal_claim_manage_create internal_claim_manage_delete internal_claim_manage_update internal_claim_manage_view internal_claim_meta_create internal_claim_meta_delete internal_claim_meta_update internal_claim_meta_view internal_config_mgt_add internal_config_mgt_delete internal_config_mgt_list internal_config_mgt_update internal_config_mgt_view internal_configure_datasources internal_configure_themes internal_consent_mgt_add internal_consent_mgt_delete internal_consent_mgt_list internal_consent_mgt_view internal_email_mgt_create internal_email_mgt_delete internal_email_mgt_update internal_email_mgt_view internal_event_publish internal_feature_management internal_functional_lib_create internal_functional_lib_delete internal_functional_lib_update internal_functional_lib_view internal_humantask_add internal_humantask_packages internal_humantask_task internal_humantask_view internal_identity_mgt_create internal_identity_mgt_delete internal_identity_mgt_update internal_identity_mgt_view internal_idp_create internal_idp_delete internal_idp_update internal_idp_view internal_keystore_create internal_keystore_delete internal_keystore_update internal_keystore_view internal_list_extensions internal_list_tenants internal_login internal_manage_event_streams internal_manage_passwords internal_manage_pep internal_manage_profiles internal_manage_provisining internal_manage_provisioning internal_manage_users internal_modify_module internal_modify_service internal_modify_tenants internal_modify_user_profile internal_modify_webapp internal_monitor_attachment internal_monitor_bpel internal_monitor_metrics internal_pap_create internal_pap_delete internal_pap_demote internal_pap_enable internal_pap_list internal_pap_order internal_pap_publish internal_pap_rollback internal_pap_subscriber_create internal_pap_subscriber_delete internal_pap_subscriber_list internal_pap_subscriber_update internal_pap_subscriber_view internal_pap_update internal_pap_view internal_pdp_manage internal_pdp_test internal_pdp_view internal_pep_manage internal_resouces_browse internal_resouces_notifications internal_role_mgt_create internal_role_mgt_delete internal_role_mgt_update internal_role_mgt_view internal_search_advanced internal_search_resouces internal_security_manage_create internal_security_manage_delete internal_security_manage_update internal_security_manage_view internal_server_admin internal_session_delete internal_session_view internal_sts_mgt_create internal_sts_mgt_delete internal_sts_mgt_update internal_sts_mgt_view internal_template_mgt_add internal_template_mgt_delete internal_template_mgt_list internal_template_mgt_view internal_topic_add internal_topic_browse internal_topic_delete internal_topic_purge internal_user_association_create internal_user_association_delete internal_user_association_update internal_user_association_view internal_user_count_create internal_user_count_delete internal_user_count_update internal_user_count_view internal_user_mgt_create internal_user_mgt_delete internal_user_mgt_list internal_user_mgt_update internal_user_mgt_view internal_user_profile_create internal_user_profile_delete internal_user_profile_update internal_user_profile_view internal_userrole_ui_create internal_userstore_create internal_userstore_delete internal_userstore_update internal_userstore_view internal_workflow_association_create internal_workflow_association_delete internal_workflow_association_update internal_workflow_association_view internal_workflow_def_create internal_workflow_def_delete internal_workflow_def_update internal_workflow_def_view internal_workflow_monitor_delete internal_workflow_monitor_view internal_workflow_profile_create internal_workflow_profile_delete internal_workflow_profile_update internal_workflow_profile_view","token_type":"Bearer","expires_in":3600}%

Surprise, WSO2 ajoute tous les scopes existants à votre token! Mais pourquoi?! Parce qu’on a pas limité les permissions applicables par-dis!

Mais comment faire ? Il n’existe pas d’UI et d’API pour les configurer! En réalité une application n’a tout simplement pas de permissions, elle hérite de celles de son propriétaire! Comme notre propriétaire est administrateur elle a donc tous les droits.

Pour arriver à nos fins il faut créer un utilisateur applicatif qui portera l’application et à qui nous donnerons les bonnes permissions.

Notre démarche sera donc la suivante :

  1. Créer un utilisateur MyApp avec un compte administrateur et lui donner le rôle admin
  2. Créer l’application MyApp avec l’utilisateur MyApp
  3. Ajouter la permission /permission/admin/manage/identity/usermgt/create au rôle Application/myapp
  4. Retirer le rôle admin à l’utilisateur MyApp

Re-testons:

curl -u 43NA43oGpOCVeqO836fLQJmoM2wa:lngPtocfBDrumojOJjfeOdDfKMMa -k -d "grant_type=client_credentials&scope=SYSTEM" -H "Content-Type:application/x-www-form-urlencoded" https://localhost:9443/oauth2/token
{"access_token":"436b28c7-ab3f-320a-b71d-cda4a4cba4c5","scope":"internal_login internal_user_mgt_create","token_type":"Bearer","expires_in":3337}

Cela fonctionne! l’application ne pourra pas modifier ou supprimer un utilisateur par exemple avec un simple token applicatif.

À savoir, il y a actuellement plusieurs freins à son usage :

  • Il est possible de connaitre et de modifier le propriétaire d’une application qu’en utilisant le web service soap OAuthAdminService et ses fonctions getConsumerApplication et updateConsumerApplication ou en interrogeant directement la table SP_APP en base de données.
  • Si vous supprimez l’utilisateur applicatif, l’application aura de nouveau accès à tout et l’ancien utilisateur sera toujours référencé comme propriétaire de l’application
  • Le propriétaire est référencé grâce à son nom d’utilisateur et n’a pas encore été migré vers un identifiant unique utilisateur. Si vous supprimez le propriétaire et que vous recréez un utilisateur avec le même identifiant celui-ci deviendra le nouveau propriétaire applicatif et l’application héritera de ses droits.

Et surtout ne pas oublier qu’il ne s’agit que d’un contrôle d’accès technique mais pas d’un contrôle d’accès métier. Si vous avez des contrôles plus fins à réaliser il faudra intervenir plus loin, avec du code spécifique via des UserOperationEventListener, dans la chaîne de traitement des requêtes par exemple.

--

--

Gregory EVE
Smile with WSO2

Solution Architect at Smile, french lover and open source supporter. Integrate, Search, Leverage and Secure your data what else?