View Javadoc
1   /*
2    * Copyright 2006-2011 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5    * the License. You may obtain a copy of the License at
6    * 
7    * https://www.apache.org/licenses/LICENSE-2.0
8    * 
9    * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10   * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11   * specific language governing permissions and limitations under the License.
12   */
13  package org.springframework.security.oauth2.provider.error;
14  
15  import java.io.IOException;
16  
17  import javax.servlet.ServletException;
18  import javax.servlet.http.HttpServletRequest;
19  import javax.servlet.http.HttpServletResponse;
20  
21  import org.springframework.http.HttpHeaders;
22  import org.springframework.http.ResponseEntity;
23  import org.springframework.security.core.AuthenticationException;
24  import org.springframework.security.oauth2.common.OAuth2AccessToken;
25  import org.springframework.security.web.AuthenticationEntryPoint;
26  import org.springframework.util.StringUtils;
27  
28  /**
29   * If authentication fails and the caller has asked for a specific content type response, this entry point can send one,
30   * along with a standard 401 status. Add to the Spring Security configuration as an {@link AuthenticationEntryPoint} in
31   * the usual way.
32   * 
33   * @author Dave Syer
34   * 
35   */
36  public class OAuth2AuthenticationEntryPoint extends AbstractOAuth2SecurityExceptionHandler implements
37  		AuthenticationEntryPoint {
38  
39  	private String typeName = OAuth2AccessToken.BEARER_TYPE;
40  
41  	private String realmName = "oauth";
42  
43  	public void setRealmName(String realmName) {
44  		this.realmName = realmName;
45  	}
46  
47  	public void setTypeName(String typeName) {
48  		this.typeName = typeName;
49  	}
50  
51  	public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
52  			throws IOException, ServletException {
53  		doHandle(request, response, authException);
54  	}
55  
56  	@Override
57  	protected ResponseEntity<?> enhanceResponse(ResponseEntity<?> response, Exception exception) {
58  		HttpHeaders headers = response.getHeaders();
59  		String existing = null;
60  		if (headers.containsKey("WWW-Authenticate")) {
61  			existing = extractTypePrefix(headers.getFirst("WWW-Authenticate"));
62  		}
63  		StringBuilder builder = new StringBuilder();
64  		builder.append(typeName+" ");
65  		builder.append("realm=\"" + realmName + "\"");
66  		if (existing!=null) {
67  			builder.append(", "+existing);
68  		}
69  		HttpHeaders update = new HttpHeaders();
70  		update.putAll(response.getHeaders());
71  		update.set("WWW-Authenticate", builder.toString());
72  		return new ResponseEntity<Object>(response.getBody(), update, response.getStatusCode());
73  	}
74  
75  	private String extractTypePrefix(String header) {
76  		String existing = header;
77  		String[] tokens = existing.split(" +");
78  		if (tokens.length > 1 && !tokens[0].endsWith(",")) {
79  			existing = StringUtils.arrayToDelimitedString(tokens, " ").substring(existing.indexOf(" ") + 1);
80  		}
81  		return existing;
82  	}
83  
84  }