Dans ce post, je donne les étapes de mise en place d’une authentification OpenID Connect (OIDC). OIDC est une couche d’identification basée sur OAuth 2.0; OIDC permet à des clients d’identifier des utilisateurs et récupérer des informations sur l’utilisateur.

OAuth2 définit plusieurs types d’authorisation; les modes sont appelés des Grant Types.

Le Grant Type utilisé dans ce post est le grant “Implicit”.

Composants Techniques

Authentification

Dans le grant Type “Implicit”, l’authentification se fait côté Front.

  • L’utilisateur ouvre le Front dans un navigateur

    • Comme l’utilisateur n’est pas authentifié, l’application le redirige vers la mire d’authentification de Keycloak
    • L’utilisateur s’authentifie en saisissant son login et mot de passe;
    • L’utilisateur est redirigé vers le Front par Keycloak (en intégrant dans l’URL un access token)
  • Toutes les requêtes Ajax du Front au Back doivent intégrer l’access token. En effet, ce token porte les informations de connexion de l’utilisateur

Configuration Keycloak

Créer un Realm

  • Créer un Realm dans Keycloak

Jenkins Job

  • Saisir le nom du Realm

Realm name

Créer un Client

  • Cliquer sur Clients dans la barre de menu à gauche

Realm name

  • Cliquer sur le bouton Create

Configurer le Client

  • Cliquer sur l’onglet Settings du Client

Config Client

  • Configurer le Client

    • Définir le Client ID (exemple : meltingpoc)

    • Définir le protocole (openid-connect)

    • Définir le type d’accès (confidential)

    • Activer le Implicit Flow

    • Préciser la liste des URL de redirection valide

Configuration côté Front

Le Front comporte deux routes :

  • une route d’authentification qui redirige l’utilisateur vers Keycloak
  • une route de post authentification qui récupère les informations de connexion à partir de l’URL

Route d’authentification

La route redirige vers l’URL d’authentification de keycloak en passant :

  • l’id du client
  • le secret du client (onglet Credentials du Client dans Keycloak)
  • le bon type de réponse attenu (id_token token)
  • l’URL de redirection après authentification
export default {
  name: 'Login',
  created() {

    window.location = 'http://keycloak.k8.wildwidewest.xyz/auth/realms/meltingpoc/protocol/openid-connect/auth?'
      + querystring.stringify({
        scope: 'read',
        client_id: 'meltingpoc',
        client_secret: '4a5bac8a-87e2-4ce1-a417-75f9f70bebef',
        response_type: "id_token token",
        redirect_uri: 'http://localhost:8080',
        grant_type: 'implicit',
        nonce: 1
      });
  }
}

querystring transforme un objet javascript en paramètres

Route Post-Authentification

Après authentification dans Keycloak, l’utilisateur est redirigé vers le Front.

La route de Post-Authentification récupère les informations de connexion de l’URL (notamment le paramètre access_token).

Appel des services Back

L’authentification des appels au Back se fait par ajout d’un header d’authorisation.

  • Le header d’authorization’ contient le mot clef ‘Bearer ‘ suivi de l’access_token (stocké ici dans le sessionStorage)
let config = {
    headers:
        {
          'Access-Control-Allow-Origin': '*',
          'Authorization': 'Bearer ' + sessionStorage.getItem("access_token"),
          'Accept': 'application/json'
        }
};

axios.get(eventURL, config)
    .then(response => {
        this.items = response.data;
    })
    .catch(e => {
        //this.errors.push(e)
    });

Configuration côté Back

Le Back développé est une application spring-boot.

Dépendance OAuth

Ajouter les dépendances suivantes au projet

compile('org.springframework.boot:spring-boot-starter')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.security.oauth:spring-security-oauth2')

Configurer OAuth

package com.meltingpoc.events.config;

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class OAuth2AuthenticationConfiguration extends ResourceServerConfigurerAdapter {

    @Bean
    public RequestMatcher resources() {
        return new RequestHeaderRequestMatcher("Authorization");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(resources())
                .authorizeRequests()
                .anyRequest().authenticated();
    }
}

Configurer CORS

Comme le Front et le Back sont deux applications différentes, il faut activer CORS au niveau du Backend.

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AjaxCorsFilter extends CorsFilter {
    public AjaxCorsFilter() {
        super(configurationSource());
    }

    private static UrlBasedCorsConfigurationSource configurationSource() {
        CorsConfiguration config = new CorsConfiguration();

        // origins
        config.addAllowedOrigin("*");

        // headers à autoriser
        config.addAllowedHeader("access-control-allow-origin");
        config.addAllowedHeader("authorization");

        // methods à autoriser
        config.addAllowedMethod(HttpMethod.OPTIONS);
        config.addAllowedMethod(HttpMethod.GET);
        config.addAllowedMethod(HttpMethod.POST);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        // liste des ressources à protéger
        source.registerCorsConfiguration("/events", config);
        return source;
    }
}

Paramétrage de l’application

Il faut paramétrer les URL OIDC dans le backend. Les URL sont décrites dans la documentation de Keycloak.

security:
  basic:
    enabled: false
  oauth2:
    resource:
      userInfoUri: http://keycloak.k8.wildwidewest.xyz/auth/realms/meltingpoc/protocol/openid-connect/userinfo
      token-info-uri: http://keycloak.k8.wildwidewest.xyz/auth/realms/meltingpoc/protocol/openid-connect/token/introspect
      prefer-token-info: false
    client:
      clientId: meltingpoc
      accessTokenUri: http://keycloak.k8.wildwidewest.xyz/auth/realms/meltingpoc/protocol/openid-connect/token
      userAuthorizationUri: http://keycloak.k8.wildwidewest.xyz/auth/realms/meltingpoc/protocol/openid-connect/auth
      scope: openid