Le socle technique (ou technologique)
Le workflow NCConnect
Spring framework
The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications - on any kind of deployment platform.
Spring Boot
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".
Spring Security
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
Spring Framework
Spring MVC
Spring Data
...
Spring Boot
Spring Security
User
Spring Security
Répond à deux problématiques de sécurité :
Spring Security
l'authentification
public interface AuthenticationManager { /** * Attempts to authenticate the passed {@link Authentication} object, returning a * fully populated <code>Authentication</code> object (including granted authorities) * if successful. */ Authentication authenticate(Authentication authentication) throws AuthenticationException; }
Elle s'appuie sur des AuthenticationProviders au travers d'un ProviderManager, à la DTSI :
AuthenticationProviders are usually tried in order until one provides a non-null response. A non-null response indicates the provider had authority to decide on the authentication request and no further providers are tried.
Spring Security
les autorisations
Elles sont incluses dans l'objet Authentication retourné par la méthode authenticate(...) sous forme d'une Collection<? extends GrantedAuthority>
Cette opération est donc bien exécutée lors de l'authentification de l'utilisateur mais reste une opération indépendante de l'authentification.
Spring Security
les autorisations (exemple)
@Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String name = authentication.getName(); String password = authentication.getCredentials().toString(); UserVO user = userDAO.findByUsername(name); if (user == null) { throw new BadCredentialsException("Authentication failed for " + name); } List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); if (new PasswordEncoderImpl().matches(password, user.getPassword())) { List<AuthorisationVO> roles = user.getRoles(); for (AuthorisationVO item : roles) { grantedAuthorities.add(new SimpleGrantedAuthority(ROLE_PREFIX + item.getAuthorisation())); } } }
Il est possible d'utiliser une implémentation de UserDetailService et UserDetails. Il faut cependant faire attention car ces implémentation ne sont pas utilisées directement pas Spring Security (qui utilise Authentication). Elles sont en fait utilisées pour avoir une représentation sémantique et plus large de l'utilisateur (incluant des informations qui ne relèvent pas toujours de la gestion de la sécurité).
Spring Security
Sécurisation des API Rest
Annotations :
Cf. GrantedAuthority.getAuthority():String si le niveau d'accès peut être représenté par une simple chaîne de caractères, ou en passant par un AccessDecisionManager pour une mise en oeuvre plus élaborée.
En complèment, pour le cas particulier de Spring Data Rest, qui expose par défaut toutes les méthodes des interfaces étendues :
@RestResource (type, méthode, attribut), et
@RepositoryRestResource (type),
permettent au travers de l'attribut exported = false de ne pas exposer les méthodes qui ne doivent pas l'être !
Spring Security
Sécurisation des API Rest
Ce qui suppose que la sécurité est également configurée au niveau de l'application :
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { (...) } @Override protected void configure(HttpSecurity http) throws Exception { http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/login**").permitAll() (...) .anyRequest().authenticated() .and() (...) } }
Spring Security
A retenir
OpenID Connect Core
OAuth 2.0 Authorization Framework
cf. IETF RFC 6749
JSON Web Token (JWT)
cf. IETF RFC 7519
User
JWT
OAuth 2.0
OpenID Connect Core
(1)
(1)
Supporte nativement OAuth 2.0
Spring Framework
Spring MVC
Spring Data
...
Spring Boot
Spring Security
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 [RFC6749] protocol. It enables Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
Ces trois éléments sont donc indissociables dans une approche OpenID Connect...
Le mécanisme d'authentification et d'autorisation peut prendre trois formes, chacune d'entre-elles déterminant la façon dont l'ID Token et l'Access Token sont renvoyés au client [RFC 6749 - The OAuth 2.0 Authorization Framework § 3.1.1 Response Type]:
Authorization Code Flow,
Implicit Flow, et
Hybrid Flow.
L'implémentation retenue dans NC Connect est Authorization Code Flow (response_type=code).
Authorization Code Flow
3 endpoints obligatoires :
3 endpoints optionels :
Type de token par point d'accès
Identity | Access | Refresh | Authorization | |
---|---|---|---|---|
Authorization | ||||
Token |
Exemple :
eyJhbGciOiJSUzUxMiJ9.eyJvYXV0aDJfcHJvdmlkZXIiOiJnZW1pbmkiLCJpc3MiOiJjb25uZWN0LXJlc291cmNlcyIsImlhdCI6MTU4MDA4NjU0MywicHJuIjoiZXlKaGJHY2lPaUpTVXpVeE1pSjkuZXlKemRXSWlPaUpoWjJWdWRFRkVMemd4TVRVM01qQm1MV1poTlRrdE5HTTNaUzFpWVRneUxURmpNR1l6TjJFeE5qWmtaU0lzSW01aGJXVWlPaUpFYVdScFpYSWdWa0ZPUkVWU1UxUlBTMFZPSWl3aVpXMWhhV3dpT2lKa2FXUnBaWEl1ZG1GdVpHVnljM1J2YTJWdUxuQnlaWE4wWVhSaGFYSmxRR2R2ZFhZdWJtTWlMQ0puYVhabGJsOXVZVzFsSWpvaVJHbGthV1Z5SWl3aVptRnRhV3g1WDI1aGJXVWlPaUpXUVU1RVJWSlRWRTlMUlU0aUxDSmxiV0ZwYkY5MlpYSnBabWxsWkNJNmRISjFaWDAuSXR5QXI4RHlaREY5Rnp1Tnhxa3JHWndQNWllZl9ER1Bha2RoZGM0SXJfSF9OcWtzT1FidjQ2OTQ2dFpRMnlQNktCM0ZnVE9HTFh5eHlYd3Qwd01GSzJ4bi1RQ2lXNi1QVmNSVm1BTHJiRmtqLXplNHdlQkV3ZzllRVJ1ZGcwSkc0SFVLOW5oQWRlWXdPMzJuZnhpbkpoUHhRMFFDSE5ZUXcwb2UwelZIRUgxenR1MXRJdkxDQjZJNG82bHlhcWM2TllHTzNqT3lkbE9GcFY3UlpaTzNLbVRzQVlfZnJoWDlVNVVzcVAzSlBKeVU4Wi1Wa3RpXzVMZUU0VzJERHlkbG5yZ3pVSjhBaVZ3UkQ1ZTBqRWlqVE5hb2M2cy1EQjFSdzlDMmZVR2JxYkVyR0c4XzAtVTZJTWNUUmxNZnZLZVNkR2kxWUdTRGpzTTZ3OWkzX3gyZlpRIiwianRpIjoiM2UzOWJkYWMtMGJlMC00ZjQ1LTk0MzgtMGY4MzBmMDU1OTQ3IiwiYXVkIjoiY29ubmVjdC1yZXNvdXJjZXMiLCJleHAiOjE1ODAwODc0NDIsImFjY2Vzc190b2tlbiI6ImV5SmhiR2NpT2lKU1V6VXhNaUo5LmV5SmhkV1FpT2lKaFkyTmxjM010ZEc5clpXNGlMQ0p6WTI5d1pTSTZXeUp2Y0dWdWFXUWlYU3dpYVhOeklqb2laMlZ0YVc1cElpd2laWGh3SWpveE5UZ3dNRGczTkRRekxDSjFjMlZ5SWpwN0ltbGtJam9pT0RFeE5UY3lNR1l0Wm1FMU9TMDBZemRsTFdKaE9ESXRNV013WmpNM1lURTJObVJsSWl3aWNISnZkbWxrWlhKSlpDSTZJbUZuWlc1MFFVUWlMQ0ptYVhKemRFNWhiV1VpT2lKRWFXUnBaWElpTENKc1lYTjBUbUZ0WlNJNklsWkJUa1JGVWxOVVQwdEZUaUlzSW1WdFlXbHNJam9pWkdsa2FXVnlMblpoYm1SbGNuTjBiMnRsYmk1d2NtVnpkR0YwWVdseVpVQm5iM1YyTG01akluMHNJbUYxZEdodmNtbDBhV1Z6SWpwYklsSlBURVZmVlZORlVpSmRMQ0pxZEdraU9pSXpNVEF5TWpKaVl5MDRZV0kxTFRReFpHWXRPR1V4WmkxbU5qSXlORGMzTldFNFpqRWlMQ0pqYkdsbGJuUmZhV1FpT2lKamIyNXVaV04wTFdGa2JXbHVMWE5vWVdSdmR5SjkuVW1mQko4Zng1NHljaUpFYzVRLW1kOGRfZGJXLVpVZ0prOHFKWUpYN0JtOVNER2FsRF9MT3plekxUOVg3ODFIRlJGSkNvMzVBUVhkQ2YtVDd0T2Q5Z0VuT25Jbnh1WWttNlNsMFlJVFdCajh4Si1hWk50cWRVbnZGTjhyRWJqTlZFbnY0MHREOHFReFRXbGZRb1VTWjBFMGJFRkJlY1lHWXVTWnZldmVscDgtU3JXeU5vOV9lc1Rsb0JiQVI3TnBoMjd5LVB0LTUzdTk1NUVLdTJ6QmdSaG1mdHdmVjBtTmFGN3JxR0duR2VjcUtvUlRTOVU3dHdzdTlrc1hKVTJzOUF6dlNCUTRJdWJqVElKMmdzWUtVYURyaFBhZVVVVFMyVWJOaXhwVHNaN1JNUm10TkJpWXZ2X21icC14Ry0zTXNhQzI3aDBwSGY3TDY0WmlqV2ZJTTNnIiwicmVmcmVzaF90b2tlbiI6ImV5SmhiR2NpT2lKU1V6VXhNaUo5LmV5SmhkV1FpT2lKeVpXWnlaWE5vTFhSdmEyVnVJaXdpYzJOdmNHVWlPbHNpYjNCbGJtbGtJbDBzSW1GMGFTSTZJak14TURJeU1tSmpMVGhoWWpVdE5ERmtaaTA0WlRGbUxXWTJNakkwTnpjMVlUaG1NU0lzSW1semN5STZJbWRsYldsdWFTSXNJbVY0Y0NJNk1UVTRNREUwTkRRd01Dd2lkWE5sY2lJNmV5SnBaQ0k2SWpneE1UVTNNakJtTFdaaE5Ua3ROR00zWlMxaVlUZ3lMVEZqTUdZek4yRXhOalprWlNJc0luQnliM1pwWkdWeVNXUWlPaUpoWjJWdWRFRkVJaXdpWm1seWMzUk9ZVzFsSWpvaVJHbGthV1Z5SWl3aWJHRnpkRTVoYldVaU9pSldRVTVFUlZKVFZFOUxSVTRpTENKbGJXRnBiQ0k2SW1ScFpHbGxjaTUyWVc1a1pYSnpkRzlyWlc0dWNISmxjM1JoZEdGcGNtVkFaMjkxZGk1dVl5SjlMQ0poZFhSb2IzSnBkR2xsY3lJNld5SlNUMHhGWDFWVFJWSWlYU3dpYW5ScElqb2lOR1EzT1RWa1ptTXROemMxTnkwMFpUWTFMVGhqTVdRdFl6VXhaVFZrWkRabFpXWmtJaXdpWTJ4cFpXNTBYMmxrSWpvaVkyOXVibVZqZEMxaFpHMXBiaTF6YUdGa2IzY2lmUS5YekFFbE96b2p4cUo3eGVpMlVJMFlLNFVDajZNVWJSWldNVWdqVVc5RWhzWnNGMlV5TGhSaW0xbi1XSG9yWDhKMi1qTjdBenpOc3NTR0RxS2NzbmZiVkYtRUlrNm1KazhkYnQ3Y25ZQU84RlRldlBCREhVZEd3NFhHSUk5c05RaWdHNGZEVkc5NU9YSzRSOVhYZXBrLWhyUmxrT1h0azFLeHo2azh3Ry1uNDRrZ3g1VzRiV055a3NQaTVWVExzZzlsMUx6akctMFVRLUFudWtVMEhmWGFKbW84NmJFVmdESm9FRjZzVkVITW1INDF6N0JWY2hPRmRDYnhnZHBQODhGYjdJNmtfYmRhN3Q3NmFDeHlyVTU0SnNOSWNla1FfUDlrbkx2ZDF4RU9lT3dOdFhoS1dza3BlbHVNZ0puanR3eFlKSG5JNkx4TG5DWlhTSzBZUVdocVEiLCJzY29wZSI6Im9wZW5pZCJ9.bVTBOB9EfuNOOoYsTPFJocrvsRrVcGjyfKCXmZ-D2E0swEKrkkJCLgcQhwU1d2Qr5AO4axaMUnf_96CdsuNCYq6SJHuKyALK9lEyMDvrRIm9jYhcRMrqtYsMNv6Vb_to-PnrIeOl0q9RyMM50wWfu7Ez2UNLfeAlEEpYQSwdwRD1qw4QM4t0F7gj78W79cPSJHubwZRkebEWJQsOKSMAMJ8sXSCJtpBk4qIsybYByLdDs66n4TMuYVUCD9_Ex2Xio7kDKE8anHpKzINFtDSl7Lz6oSUSnGrcKnxeGuKtxJwc3DD_DPkVzx-fdwfvZZRSqeKZS-Sq-mERMZJkP-hj6A
Exemple (suite) :
header (Algorythme & type de token) :
{
"alg": "RS512"
}
Exemple (suite) :
payload :
{
"oauth2_provider": "gemini",
"iss": "connect-resources",
"iat": 1580086543,
"prn": "eyJhbGciOiJSUzUxMiJ9.eyJzdWIiOiJhZ2VudEFELzgxMTU3MjBmLWZhNTktNGM3ZS1iYTgyLTFjMGYzN2ExNjZkZSIsIm5hbWUiOiJEaWRpZXIgVkFOREVSU1RPS0VOIiwiZW1haWwiOiJkaWRpZXIudmFuZGVyc3Rva2VuLnByZXN0YXRhaXJlQGdvdXYubmMiLCJnaXZlbl9uYW1lIjoiRGlkaWVyIiwiZmFtaWx5X25hbWUiOiJWQU5ERVJTVE9LRU4iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZX0.ItyAr8DyZDF9FzuNxqkrGZwP5ief_DGPakdhdc4Ir_H_NqksOQbv46946tZQ2yP6KB3FgTOGLXyxyXwt0wMFK2xn-QCiW6-PVcRVmALrbFkj-ze4weBEwg9eERudg0JG4HUK9nhAdeYwO32nfxinJhPxQ0QCHNYQw0oe0zVHEH1ztu1tIvLCB6I4o6lyaqc6NYGO3jOydlOFpV7RZZO3KmTsAY_frhX9U5UsqP3JPJyU8Z-Vkti_5LeE4W2DDydlnrgzUJ8AiVwRD5e0jEijTNaoc6s-DB1Rw9C2fUGbqbErGG8_0-U6IMcTRlMfvKeSdGi1YGSDjsM6w9i3_x2fZQ",
"jti": "3e39bdac-0be0-4f45-9438-0f830f055947",
"aud": "connect-resources",
"exp": 1580087442,
"access_token": "eyJhbGciOiJSUzUxMiJ9.eyJhdWQiOiJhY2Nlc3MtdG9rZW4iLCJzY29wZSI6WyJvcGVuaWQiXSwiaXNzIjoiZ2VtaW5pIiwiZXhwIjoxNTgwMDg3NDQzLCJ1c2VyIjp7ImlkIjoiODExNTcyMGYtZmE1OS00YzdlLWJhODItMWMwZjM3YTE2NmRlIiwicHJvdmlkZXJJZCI6ImFnZW50QUQiLCJmaXJzdE5hbWUiOiJEaWRpZXIiLCJsYXN0TmFtZSI6IlZBTkRFUlNUT0tFTiIsImVtYWlsIjoiZGlkaWVyLnZhbmRlcnN0b2tlbi5wcmVzdGF0YWlyZUBnb3V2Lm5jIn0sImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiIzMTAyMjJiYy04YWI1LTQxZGYtOGUxZi1mNjIyNDc3NWE4ZjEiLCJjbGllbnRfaWQiOiJjb25uZWN0LWFkbWluLXNoYWRvdyJ9.UmfBJ8fx54yciJEc5Q-md8d_dbW-ZUgJk8qJYJX7Bm9SDGalD_LOzezLT9X781HFRFJCo35AQXdCf-T7tOd9gEnOnInxuYkm6Sl0YITWBj8xJ-aZNtqdUnvFN8rEbjNVEnv40tD8qQxTWlfQoUSZ0E0bEFBecYGYuSZvevelp8-SrWyNo9_esTloBbAR7Nph27y-Pt-53u955EKu2zBgRhmftwfV0mNaF7rqGGnGecqKoRTS9U7twsu9ksXJU2s9AzvSBQ4IubjTIJ2gsYKUaDrhPaeUUTS2UbNixpTsZ7RMRmtNBiYvv_mbp-xG-3MsaC27h0pHf7L64ZijWfIM3g",
"refresh_token": "eyJhbGciOiJSUzUxMiJ9.eyJhdWQiOiJyZWZyZXNoLXRva2VuIiwic2NvcGUiOlsib3BlbmlkIl0sImF0aSI6IjMxMDIyMmJjLThhYjUtNDFkZi04ZTFmLWY2MjI0Nzc1YThmMSIsImlzcyI6ImdlbWluaSIsImV4cCI6MTU4MDE0NDQwMCwidXNlciI6eyJpZCI6IjgxMTU3MjBmLWZhNTktNGM3ZS1iYTgyLTFjMGYzN2ExNjZkZSIsInByb3ZpZGVySWQiOiJhZ2VudEFEIiwiZmlyc3ROYW1lIjoiRGlkaWVyIiwibGFzdE5hbWUiOiJWQU5ERVJTVE9LRU4iLCJlbWFpbCI6ImRpZGllci52YW5kZXJzdG9rZW4ucHJlc3RhdGFpcmVAZ291di5uYyJ9LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiNGQ3OTVkZmMtNzc1Ny00ZTY1LThjMWQtYzUxZTVkZDZlZWZkIiwiY2xpZW50X2lkIjoiY29ubmVjdC1hZG1pbi1zaGFkb3cifQ.XzAElOzojxqJ7xei2UI0YK4UCj6MUbRZWMUgjUW9EhsZsF2UyLhRim1n-WHorX8J2-jN7AzzNssSGDqKcsnfbVF-EIk6mJk8dbt7cnYAO8FTevPBDHUdGw4XGII9sNQigG4fDVG95OXK4R9XXepk-hrRlkOXtk1Kxz6k8wG-n44kgx5W4bWNyksPi5VTLsg9l1LzjG-0UQ-AnukU0HfXaJmo86bEVgDJoEF6sVEHMmH41z7BVchOFdCbxgdpP88Fb7I6k_bda7t76aCxyrU54JsNIcekQ_P9knLvd1xEOeOwNtXhKWskpeluMgJnjtwxYJHnI6LxLnCZXSK0YQWhqQ",
"scope": "openid"
}
Exemple (suite) :
access-token:
{ "aud": "access-token", "scope": [ "openid" ], "iss": "gemini", "exp": 1580087443, "user": { "id": "8115720f-fa59-4c7e-ba82-1c0f37a166de", "providerId": "agentAD", "firstName": "Didier", "lastName": "VANDERSTOKEN", "email": "didier.vanderstoken.prestataire@gouv.nc" }, "authorities": [ "ROLE_USER" ], "jti": "310222bc-8ab5-41df-8e1f-f6224775a8f1", "client_id": "connect-admin-shadow" }
JWT constitue l'enveloppe standard d'échange des informations (des tokens).
Il est constitué de 3 parties :
Questions