001    /*
002     * Copyright 2011-2012 UnboundID Corp.
003     *
004     * This program is free software; you can redistribute it and/or modify
005     * it under the terms of the GNU General Public License (GPLv2 only)
006     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
007     * as published by the Free Software Foundation.
008     *
009     * This program is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012     * GNU General Public License for more details.
013     *
014     * You should have received a copy of the GNU General Public License
015     * along with this program; if not, see <http://www.gnu.org/licenses>.
016     */
017    
018    package com.unboundid.scim.sdk;
019    
020    import org.apache.wink.client.ClientAuthenticationException;
021    import org.apache.wink.client.ClientRequest;
022    import org.apache.wink.client.ClientResponse;
023    import org.apache.wink.client.handlers.ClientHandler;
024    import org.apache.wink.client.handlers.HandlerContext;
025    import org.apache.wink.common.http.HttpStatus;
026    
027    import javax.xml.bind.DatatypeConverter;
028    import java.io.InputStream;
029    
030    /**
031     * This class provides HTTP Basic Authentication handling.
032     */
033    public class HttpBasicAuthSecurityHandler implements ClientHandler {
034      private volatile String username;
035      private volatile String encodedCredentials;
036    
037      /**
038       * Constructs a fully initialized Security handler.
039       * @param username The Consumer username.
040       * @param password The Consumer password.
041       */
042      public HttpBasicAuthSecurityHandler(final String username,
043        final String password) {
044        this.username = username;
045        String encoded = DatatypeConverter.printBase64Binary(
046            (username + ":" + password).getBytes());
047        this.encodedCredentials = "Basic " + encoded;
048      }
049    
050      /**
051       * Attempts to authenticate a Consumer via Http Basic.
052       *
053       * @param request  The Client Resource request.
054       * @param context The provided handler chain.
055       * @return Client Response that may indicate success or failure.
056       * @throws Exception Thrown if error handling authentication.
057       */
058      public ClientResponse handle(final ClientRequest request,
059        final HandlerContext context) throws Exception {
060        ClientResponse response = context.doChain(request);
061        if (response.getStatusCode() == HttpStatus.UNAUTHORIZED.getCode()) {
062          InputStream is = response.getEntity(InputStream.class);
063          if(is != null) {
064            // Throw away any entity content.
065            is.close();
066          }
067          request.getHeaders().putSingle("Authorization", this.encodedCredentials);
068          response = context.doChain(request);
069          if (response.getStatusCode() == HttpStatus.UNAUTHORIZED.getCode()) {
070            throw new ClientAuthenticationException(username);
071          } else {
072            // error presumably unrelated to authentication
073            return response;
074          }
075        } else {
076          return response;
077        }
078      }
079    }