Authentification avec AzureAD

Authentification avec AzureAD
0
Tags: #<Tag:0x00007f76976a10c0>

Bonjour,

J’interface Simplicité à un annuaire AzureAD (compatible OpenID Connect).
Je souhaite donc créer les utilisateurs, les groupes et les relations utilisateurs / groupe au moment de l’authentification.
J’utilise pour cela les GrantHook :
https://www.simplicite.io/resources/documentation/01-core/grant-code-hooks.md
https://www.simplicite.io/resources/4.0/javadoc/com/simplicite/util/GrantHooksInterface.html

Avant de créer l’utilisateur, j’ai également besoin de récupérer le jeton ‘access token’ OpenID Connect pour appeler l’API Microsoft https://graph.microsoft.com et requêter les attributs utilisateurs. Le principe est décrit ici:
https://docs.microsoft.com/fr-fr/azure/active-directory/develop/v2-oauth2-auth-code-flow

Pouvez-vous m’indiquer comment récupérer le jeton ‘access token’ via l’API Java de Simplicité ?
Auriez vous un exemple de code en Java pour créer un utilisateur lors de l’authentification, et attribuer l’utilisateur à des rôles préalablement déclarés ?

Merci pour votre aide.

Voici déjà un exemple de création de user dans le preLoadGrant:

	public static void preLoadGrant(Grant g) {
		Grant sys = Grant.getSystemAdmin();

		if (g.isOAuth2AuthMethod()) try { // only if OAuth2 auth method
			String login = g.getLogin();
			if (Tool.isEmpty(login))
				throw new AuthenticationException("Empty login");

			// Create user if needed
			if (!Grant.exists(login, false)) {
				ObjectDB usr = sys.getTmpObject("User");
				synchronized (usr) { // thread-safe
					usr.resetValues(true);
					usr.setRowId(ObjectField.DEFAULT_ROW_ID);
					usr.getField("usr_login").setValue(login);
					usr.setFieldValue("usr_lang", Globals.LANG_FRENCH);
					usr.setFieldValue("usr_home_id", View.getViewId(sys.getParameter("DEFAULT_USER_HOME", "Home")));
					usr.setStatus(Grant.USER_ACTIVE);
					AppLog.info(GrantHooks.class, "preLoadGrant", "User to create " + usr.toJSONObject().toString(2), sys);
					new BusinessObjectTool(usr).validateAndCreate();

					String module = usr.getFieldValue("row_module_id.mdl_name");
					AppLog.info(GrantHooks.class, "preLoadGrant", "Created user " + login + " in module " + module, sys);

					String group = sys.getParameter("DEFAULT_USER_GROUP", "");
					if (!Tool.isEmpty(group)) {
						Grant.addResponsibility(usr.getRowId(), group, Tool.getCurrentDate(-1), "", true, module);
						AppLog.info(GrantHooks.class, "preLoadGrant", "Added " + group + " responsibility for user " + login, sys);
					}
				}
			}
		} catch (Exception e) {
			AppLog.error(GrantHooks.class, "preLoadGrant", null, e, sys);
		}
	}

Je regarde le point sur le changement du login et je te fais un retour.

Pour les appels de services je te recommande d’utiliser RESTTool cf. https://docs.simplicite.io/4.0/javadoc/com/simplicite/util/tools/RESTTool.html

Pour préciser le besoin :
Dans le protocole OpenID Connect, lors de l’appel au endpoint /token, on reçoit une réponse de ce type :

{
“access_token”: “eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q…”,
“token_type”: “Bearer”,
“expires_in”: 3599,
“scope”: “https%3A%2F%2Fgraph.microsoft.com%2Fmail.read”,
“refresh_token”: “AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4…”,
“id_token”: “eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD…”,
}

Simplicité décode le ‘id_token’, et on retrouve cet ‘id_token’ dans l’objet SessionInfo.
Mais par contre, l’API ne fournit pas d’accès aux tokens “access_token” et “refresh_token” qui sont nécessaires pour appeler des API gérées par le fournisseur d’identité OIDC.

La classe GoogleAPITool semble fournir ces infos via les méthodes getToken & refreshToken ?
Il faudrait idéalement avoir ce type de méthode pour tout type de provider OIDC.

Je vais vérifier mais les infos obtenues lors des échanges d’autent sont normalement toutes conservées dans le session info. Je vous tiens au courant

Effectivement, contrairement au cas particulier OAuth2 Google, toutes les infos ne sont pas conservées dans le cas du connecteur générique OpenIDConnect. On est en train de faire les évolutions pour que ce soit le cas.

Je vous tiendrai au courant quand ce sera backporté sur les branches (preàrelease.

C’est en place (testé avec Google en mode OpenIDConnect) j’espère que ça marchera iso dans votre cas.

Les 3 tokens sont désormais disponibles dans le session info SessionInfo info = <grant>.getSessionInfo() (où <grant> dépend du contexte, ex: dans un objet interne ou externe c’est getGrant()). Cf. https://docs.simplicite.io/4.0/javadoc/com/simplicite/util/SessionInfo.html

  • Access token: info.getToken()
  • ID token: info.getIDToken()
  • Refresh token: info.getRefreshToken() (avec Google celui ci n’est pas systématiquement fourni)

ex: traces dans un GratHooks.preLoadGrant():

public static void preLoadGrant(Grant g) {
	try {
		AppLog.info(GrantHooks.class, "postLoadGrant",
			"Grant " + g.getLogin() +
			", access token " + g.getSessionInfo().getToken() +
			", ID token " + g.getSessionInfo().getIDToken() +
			", refresh token " + g.getSessionInfo().getRefreshToken()
			", session info " + g.getSessionInfo().toString(), null);
	} catch (Throwable e) {
		AppLog.error(GrantHooks.class, "preLoadGrant", null, e, null);
	}
}

Attention dans un preLoadGrant le grant g ne contient pas encore grand chose, essentiellement le login et, justement, le session info issu de l’authentification, le reste se charge plus tard dans le load.

Bonjour,

Notre plateforme a été mise à jour avec la dernière version (4.0 patch level P24Built on2020-03-04 22:57).
J’ai maintenant accès aux 3 tokens OIDC (access, refresh et ID token) et je peux récupérer les attributs utilisateurs en appelant l’API Microsoft Graph.

Par contre, le premier code d’exemple ci-dessus ne fonctionne pas comme voulu.

Avec AzureAD, l’appel au enpoint /userinfo renvoi une chaîne très limitée du type :
{
“sub”: “Q5IqbVBjeZIUtkBs9yLm-Mg3nhobR_N2y1XC7Sn6HLU”,
“name”: “Alice Green”,
“family_name”: “Green”,
“given_name”: “Alice”,
“picture”: “https://graph.microsoft.com/v1.0/me/photo/$value
}

Dans le preLoadGrant, je crée donc un utilisateur s’il n’existe pas, avec les attributs récupérés auparavant avec l’API Microsoft.
Je modifie le login pour remplacer l’ID opaque (champ ‘sub’) fourni par AzureAD par le vrai login (champ ‘upn’ ou userPrincipalName, accessible dans l’access token ou le ID token).
=> dans preLoadGrant(Grant g), j’appelle donc g.setLogin(login)
Le résultat est que je me retrouve avec 2 users en base :

  • celui que j’ai créé
  • celui avec le login opaque
    De plus je suis loggé ave le premier user et donc je n’ai pas les bons droits.

J’ai tenté d’intervenir en amont via la variable OAUTH2_USERINFO_MAPPINGS, l’idée étant de remplacer au plus tôt le login
{ “login”: “upn” }
Mais le mapping ne semble lire que les champs récupérés auprès de OAUTH2_USERINFO_URL donc il ne se passe rien.

J’ai tenté d’intervenir auprès le la méthode GrantHooks.parseAuth mais cette méthode n’est pas appelée.

Existe-t-il un moyen de créer les utilisateurs à la volée en leur attribuant un login spécifique ?

En l’état, le mapping “login” ne cherche effectivement que dans le JSON userinfo.

SI je comprend bien, l’attribut upn n’est pas dans le userinfo mais dans la réponse du token. Puis-je avoir un exemple ? Merci

Voici un exemple d’access token décodé et de ID token décodé.
Ici, j’ai configuré Azure AD pour qu’il renvoi le champ upn (entre autre).
Le principe est décrit ici: https://docs.microsoft.com/fr-fr/azure/active-directory/develop/active-directory-optional-claims#configuring-groups-optional-claims
Mais je peux aussi récupérer le login ou tout autre attribut via un appel à l’API Microsoft dans la méthode preLoadGrant.

Access token

{
“typ”: “JWT”,
“nonce”: “Mq85GOUCbOdUbLPj6Dg0uVEoXwfQqdul59tb3yE5dAc”,
“alg”: “RS256”,
“x5t”: “HlC0R12skxNZ1WQwmjOF_6t_tDE”,
“kid”: “HlC0R12skxNZ1WQwmjOF_6t_tDE”
}.{
“aud”: “00000003-0000-0000-c000-000000000000”,
“iss”: “https://sts.windows.net/3ec31dbb-6f03-4141-a210-63354b279757/”,
“iat”: 1581590321,
“nbf”: 1581590321,
“exp”: 1581594221,
“acct”: 0,
“acr”: “1”,
“aio”: “42NgYLALMYxb11bR9ebYTMGEyf6d12e7nl9pW2W/O6vpi92Fo98B”,
“amr”: [
“pwd”
],
“app_displayname”: “NAMe”,
“appid”: “1abed652-a82d-4f81-b813-5018232fcaa8”,
“appidacr”: “1”,
“family_name”: “Green”,
“given_name”: “Alice”,
“ipaddr”: “194.2.202.85”,
“name”: “Alice Green”,
“oid”: “96bc219c-5361-43d0-96e9-f448259d4035”,
“platf”: “3”,
“puid”: “1003200099B3E5A1”,
“scp”: “Directory.Read.All User.Read User.Read.All profile openid email”,
“signin_state”: [
“kmsi”
],
“sub”: “HPuGsG2poodsPyTThMOHptrmIt3XGsKpoeUsNlOZgS0”,
“tid”: “3ec31dbb-6f03-4141-a210-63354b279757”,
“unique_name”: “alice@epidead.onmicrosoft.com”,
“upn”: “alice@epidead.onmicrosoft.com”,
“uti”: “zFdBL-nRA0eGt44lvqydAA”,
“ver”: “1.0”,
“xms_st”: {
“sub”: “Q5IqbVBjeZIUtkBs9yLm-Mg3nhobR_N2y1XC7Sn6HLU”
},
“xms_tcdt”: 1580897789
}.[Signature]

ID Token

{
“typ”: “JWT”,
“alg”: “RS256”,
“kid”: “HlC0R12skxNZ1WQwmjOF_6t_tDE”
}.{
“aud”: “1abed652-a82d-4f81-b813-5018232fcaa8”,
“iss”: “https://login.microsoftonline.com/3ec31dbb-6f03-4141-a210-63354b279757/v2.0”,
“iat”: 1581591215,
“nbf”: 1581591215,
“exp”: 1581595115,
“acct”: 0,
“aio”: “ATQAy/8OAAAAGBGEpBylxNQpgormBkzkgS5rubTguO1oOe95y5r7if/YsaZyyFVpka9N/j86ErB/”,
“family_name”: “Green”,
“given_name”: “Alice”,
“groups”: [
“1eab7446-2bec-4600-b359-ca6d5a1261af”
],
“ipaddr”: “194.2.202.85”,
“name”: “Alice Green”,
“oid”: “96bc219c-5361-43d0-96e9-f448259d4035”,
“preferred_username”: “alice@epidead.onmicrosoft.com”,
“roles”: [
“Writer”
],
“sub”: “Q5IqbVBjeZIUtkBs9yLm-Mg3nhobR_N2y1XC7Sn6HLU”,
“tid”: “3ec31dbb-6f03-4141-a210-63354b279757”,
“upn”: “alice@epidead.onmicrosoft.com”,
“uti”: “xa3Dy54x8kCoQg0ySoSSAA”,
“ver”: “2.0”
}.[Signature]