001/*
002 * Copyright 2011-2013 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
018package com.unboundid.scim.sdk;
019
020import org.apache.wink.client.ClientRequest;
021import org.apache.wink.client.ClientResponse;
022import org.apache.wink.client.handlers.ClientHandler;
023import org.apache.wink.client.handlers.HandlerContext;
024import org.apache.wink.common.http.HttpStatus;
025
026import javax.xml.bind.DatatypeConverter;
027import java.io.InputStream;
028import java.io.UnsupportedEncodingException;
029
030
031/**
032 * This class provides HTTP Basic Authentication handling.
033 */
034public class HttpBasicAuthSecurityHandler implements ClientHandler
035{
036
037  private volatile String encodedCredentials;
038
039  /**
040   * Constructs a fully initialized Security handler.
041   * @param username The Consumer username.
042   * @param password The Consumer password.
043   */
044  public HttpBasicAuthSecurityHandler(final String username,
045                                      final String password)
046  {
047    String encoded = null;
048    try
049    {
050      encoded = DatatypeConverter.printBase64Binary(
051              (username + ":" + password).getBytes("UTF-8"));
052    }
053    catch(UnsupportedEncodingException e)
054    {
055      //UTF-8 is pretty standard, so this should not happen.
056      throw new IllegalArgumentException(e.getMessage());
057    }
058    this.encodedCredentials = "Basic " + encoded;
059  }
060
061  /**
062   * Attempts to authenticate a Consumer via Http Basic.
063   *
064   * @param request  The Client Resource request.
065   * @param context The provided handler chain.
066   * @return Client Response that may indicate success or failure.
067   * @throws Exception Thrown if error handling authentication.
068   */
069  public ClientResponse handle(final ClientRequest request,
070                               final HandlerContext context) throws Exception
071  {
072    ClientResponse response = context.doChain(request);
073    if (response.getStatusCode() == HttpStatus.UNAUTHORIZED.getCode())
074    {
075      InputStream is = response.getEntity(InputStream.class);
076      if(is != null) {
077        // Throw away any entity content.
078        is.close();
079      }
080      request.getHeaders().putSingle("Authorization", this.encodedCredentials);
081      return context.doChain(request);
082    }
083    else
084    {
085      return response;
086    }
087  }
088}