Exemplo utilizando Java

Antes de Começar

Certifique-se de que você tem todos os dados descritos aqui antes de seguir o tutorial.

Dependências

Para conectar no Login Cidadão usando Java é utilizado o cliente OAuth Apache Oltu. Nesse exemplo, será utilizado o gerenciador de dependencias Maven. Assim, no pom.xml do projeto é necessario adicionar as seguintes dependencias:

    <properties>
        <oltu.oauth2.version>1.0.0</oltu.oauth2.version>
    </properties>
    <dependencies>
        <!-- idm deps -->
        <dependency>
            <artifactId>org.apache.oltu.oauth2.common</artifactId>
            <groupId>org.apache.oltu.oauth2</groupId>
            <version>${oltu.oauth2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.oltu.oauth2</groupId>
            <artifactId>org.apache.oltu.oauth2.client</artifactId>
            <version>${oltu.oauth2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.oltu.oauth2</groupId>
            <artifactId>org.apache.oltu.oauth2.jwt</artifactId>
            <version>${oltu.oauth2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.oltu.oauth2</groupId>
            <artifactId>org.apache.oltu.oauth2.dynamicreg.client</artifactId>
            <version>${oltu.oauth2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.oltu.oauth2</groupId>
            <artifactId>org.apache.oltu.oauth2.dynamicreg.common</artifactId>
            <version>${oltu.oauth2.version}</version>
        </dependency>       
        <!-- json utils -->
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.13</version>
        </dependency>       
    </dependencies>

Começando

Arquivo de configuração

Primeiramente criamos um arquivo de configuração oauth_configuration.properties referente ao servidor OAuth que desejamos utilizar. Nesse arquivo, especificamos o tipo de aplicação que o Apache Oltu utilizará, especificamos o endereço para fazer a autenticação, o endereço para obter o Access Token, endereço para obter os dados do usuário, os escopos desejados, a chave pública, a chave privada e o endereço para onde o gerenciador de identidades irá retornar os dados :

//tipo de aplicação que o Apache Oltu utilizará
application=generic

//endereço para fazer a autenticação
authz_endpoint=https://meu.rs.gov.br/oauth/v2/auth

//endereço para obter a Access Token
token_endpoint=https://meu.rs.gov.br/oauth/v2/token

//endereço para obter os dados do usuário
resource_url=https://meu.rs.gov.br/api/v1/person

//escopos desejados
scope=

//chave pública
client_id=

//chave privada
client_secret=

//endereço para onde o gerenciador de identidades irá retornar dados
redirect_uri=

Criando um filtro de autenticação

É necessário criar um filtro utilizando javax.servlet.Filter. Para isso utilizamos o arquivo src/main/java/br/gov/rs/meu/helper/AuthFilter.java da seguinte forma:

// src/main/java/br/gov/rs/meu/helper/AuthFilter.java

@WebFilter(urlPatterns = { Utils.REDIRECT_URI })
public class AuthFilter implements Filter {
    // ...
}

Na a anotação @WebFilter nos adicionamos como um dos endereços filtrados o endereço para aonde o gerenciador de identidades retornará dados.

// src/main/java/br/gov/rs/meu/helper/AuthFilter.java

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        try {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse res = (HttpServletResponse) response;
            HttpSession ses = req.getSession(false);

            // Guardamos o endereço que o usuário está tentando acessar
            String reqURI = req.getRequestURI();

            // Verificamos se o usuário já está autenticado nesta aplicação
            if ((ses != null && ses.getAttribute("username") != null) || reqURI.contains("javax.faces.resource") || Utils.inArray(reqURI, whiteList)) {
                chain.doFilter(request, response);
            } else {
                // Ele não está autenticado, mas pode estar em processo de autenticação
                if (ses != null && ses.getAttribute("lc.oauthParams") != null) {
                    // Obtemos os parâmetros de autenticação
                    OAuthParams oauthParams = (OAuthParams) ses.getAttribute("lc.oauthParams");
                    OAuthAuthzResponse oar = OAuthAuthzResponse.oauthCodeAuthzResponse(req);

                    // e verificamos se recebemos um Authorization Code
                    oauthParams.setAuthzCode(oar.getCode());

                    // Solicitamos um Access Token
                    Utils.getAuthorizationToken(oauthParams);

                    // e, em seguida, solicitamos os dados do usuário
                    Utils.getResource(oauthParams);

                    // Para simplificar, armazenamos os dados em um Map
                    // Naturalmente você deveria desserializar o JSON recebido
                    // para um objeto apropriado
                    ObjectMapper mapper = new ObjectMapper();                   
                    Map<String, Object> person = mapper.readValue(
                            oauthParams.getResource(),
                            new TypeReference<Map<String, Object>>() {
                            });

                    // Nesse momento já possuimos os dados do usuário
                    // É nesse ponto que você deve persistir o usuário juntamente com
                    // Seus Access e Refresh Tokens
                    // Como isto é apenas um exemplo vamos apenas salvar na sessão
                    ses.setAttribute("username", person);

                    // Encaminhamos o usuário para onde ele tentou ir originalmente
                    res.sendRedirect((String) ses.getAttribute("lc.origTarget"));
                    ses.removeAttribute("lc.origTarget");
                } else {
                    // O usuário não está autenticado nem está se autenticando
                    // Então devemos encaminhá-lo para o gerenciador de identidade

                    // É uma boa prática salvar a URL que o usuário tentou acessar
                    // para encaminhá-lo depois da autorização e autenticação.
                    String origTarget = Utils.getFullRequestURL(req);

                    // Preparamos as configurações do gerenciador de identidade
                    OAuthParams oauthParams = Utils.prepareOAuthParams(req);
                    OAuthClientRequest oauthRequest = OAuthClientRequest
                            .authorizationLocation(
                                    oauthParams.getAuthzEndpoint())
                            .setClientId(oauthParams.getClientId())
                            .setRedirectURI(oauthParams.getRedirectUri())
                            .setResponseType(ResponseType.CODE.toString())
                            .setScope(oauthParams.getScope())
                            .setState(oauthParams.getState())
                            .buildQueryMessage();

                    // Salvemos na sessão as configurações do gerenciador de identidade
                    ses.setAttribute("lc.oauthParams", oauthParams);
                    ses.setAttribute("lc.origTarget", origTarget);

                    // Redirecionamos o usuário para o gerenciador de identidades
                    res.sendRedirect(oauthRequest.getLocationUri());
                }
            }

        } catch (Throwable t) {
            System.out.println(t.getMessage());
        }

    }

No arquivo src/main/java/br/gov/rs/meu/helper/Utils.java merece explicação dois metodos: getAuthorizationToken e o getResource. O metodo getAuthorizationToken é responsável por obter a Access Token:

public static void getAuthorizationToken(OAuthParams oauthParams) throws OAuthSystemException, OAuthProblemException {
    //Preparamos as configurações do gerenciador de identidade
    OAuthClientRequest oRequest = OAuthClientRequest
            .tokenLocation(oauthParams.getTokenEndpoint())
            .setClientId(oauthParams.getClientId())
            .setClientSecret(oauthParams.getClientSecret())
            .setRedirectURI(oauthParams.getRedirectUri())
            .setCode(oauthParams.getAuthzCode())
            .setGrantType(GrantType.AUTHORIZATION_CODE).buildBodyMessage();

    OAuthClient client = new OAuthClient(new URLConnectionClient());

    OAuthAccessTokenResponse oauthResponse = null;
    //definimos uma classe genérica para receber a Access Token
    Class<? extends OAuthAccessTokenResponse> cl = OAuthJSONAccessTokenResponse.class;
    //requisitamos ao gerenciador de identidade uma Access Token para
    oauthResponse = client.accessToken(oRequest, cl);
    //salve a Access Token, a Refresh Token e a data de expiração
    oauthParams.setAccessToken(oauthResponse.getAccessToken());
    oauthParams.setExpiresIn(oauthResponse.getExpiresIn());
    oauthParams.setRefreshToken(oauthResponse.getRefreshToken());
}

O metodo getResource é responsável por obter os dados do usuário:

public static void getResource(OAuthParams oauthParams) throws OAuthSystemException, OAuthProblemException {
    OAuthClientRequest request = null;
    //escolhemos a forma que enviamos a nossa Access Token para o gerenciador de identidades
    if (Utils.REQUEST_TYPE_QUERY.equals(oauthParams.getRequestType())) {
        request = new OAuthBearerClientRequest(oauthParams.getResourceUrl())
                .setAccessToken(oauthParams.getAccessToken())
                .buildQueryMessage();
    } else if (Utils.REQUEST_TYPE_HEADER.equals(oauthParams
            .getRequestType())) {
        request = new OAuthBearerClientRequest(oauthParams.getResourceUrl())
                .setAccessToken(oauthParams.getAccessToken())
                .buildHeaderMessage();
    } else if (Utils.REQUEST_TYPE_BODY.equals(oauthParams.getRequestType())) {
        request = new OAuthBearerClientRequest(oauthParams.getResourceUrl())
                .setAccessToken(oauthParams.getAccessToken())
                .buildBodyMessage();
    }

    OAuthClient client = new OAuthClient(new URLConnectionClient());
    //requisitamos ao gerenciador de identidade os dados do usuário
    OAuthResourceResponse resourceResponse = client.resource(request,
            oauthParams.getRequestMethod(), OAuthResourceResponse.class);

    //caso tenha uma resposta positiva do gerenciador de identidade salve a resposta
    if (resourceResponse.getResponseCode() == 200) {
        oauthParams.setResource(resourceResponse.getBody());
    } else {
        oauthParams.setErrorMessage("Could not access resource: "
                + resourceResponse.getResponseCode() + " "
                + resourceResponse.getBody());
    }
}