View Javadoc
1   package org.springframework.security.oauth2.common.exceptions;
2   
3   import java.util.Map;
4   import java.util.Set;
5   import java.util.TreeMap;
6   
7   /**
8    * Base exception for OAuth 2 exceptions.
9    * 
10   * @author Ryan Heaton
11   * @author Rob Winch
12   * @author Dave Syer
13   */
14  @SuppressWarnings("serial")
15  @com.fasterxml.jackson.databind.annotation.JsonSerialize(using = OAuth2ExceptionJackson2Serializer.class)
16  @com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = OAuth2ExceptionJackson2Deserializer.class)
17  public class OAuth2Exception extends RuntimeException {
18  
19  	public static final String ERROR = "error";
20  	public static final String DESCRIPTION = "error_description";
21  	public static final String URI = "error_uri";
22  	public static final String INVALID_REQUEST = "invalid_request";
23  	public static final String INVALID_CLIENT = "invalid_client";
24  	public static final String INVALID_GRANT = "invalid_grant";
25  	public static final String UNAUTHORIZED_CLIENT = "unauthorized_client";
26  	public static final String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type";
27  	public static final String INVALID_SCOPE = "invalid_scope";
28  	public static final String INSUFFICIENT_SCOPE = "insufficient_scope";
29  	public static final String INVALID_TOKEN = "invalid_token";
30  	public static final String REDIRECT_URI_MISMATCH ="redirect_uri_mismatch";
31  	public static final String UNSUPPORTED_RESPONSE_TYPE ="unsupported_response_type";
32  	public static final String ACCESS_DENIED = "access_denied";
33  
34  	private Map<String, String> additionalInformation = null;
35  
36  	public OAuth2Exception(String msg, Throwable t) {
37  		super(msg, t);
38  	}
39  
40  	public OAuth2Exception(String msg) {
41  		super(msg);
42  	}
43  
44  	/**
45  	 * The OAuth2 error code.
46  	 * 
47  	 * @return The OAuth2 error code.
48  	 */
49  	public String getOAuth2ErrorCode() {
50  		return "invalid_request";
51  	}
52  
53  	/**
54  	 * The HTTP error code associated with this error.
55  	 * 
56  	 * @return The HTTP error code associated with this error.
57  	 */
58  	public int getHttpErrorCode() {
59  		return 400;
60  	}
61  
62  	/**
63  	 * Get any additional information associated with this error.
64  	 * 
65  	 * @return Additional information, or null if none.
66  	 */
67  	public Map<String, String> getAdditionalInformation() {
68  		return this.additionalInformation;
69  	}
70  
71  	/**
72  	 * Add some additional information with this OAuth error.
73  	 * 
74  	 * @param key The key.
75  	 * @param value The value.
76  	 */
77  	public void addAdditionalInformation(String key, String value) {
78  		if (this.additionalInformation == null) {
79  			this.additionalInformation = new TreeMap<String, String>();
80  		}
81  
82  		this.additionalInformation.put(key, value);
83  
84  	}
85  
86  	/**
87  	 * Creates the appropriate subclass of OAuth2Exception given the errorCode.
88  	 * @param errorCode
89  	 * @param errorMessage
90  	 * @return
91  	 */
92  	public static OAuth2Exception create(String errorCode, String errorMessage) {
93  		if (errorMessage == null) {
94  			errorMessage = errorCode == null ? "OAuth Error" : errorCode;
95  		}
96  		if (INVALID_CLIENT.equals(errorCode)) {
97  			return new InvalidClientException(errorMessage);
98  		}
99  		else if (UNAUTHORIZED_CLIENT.equals(errorCode)) {
100 			return new UnauthorizedClientException(errorMessage);
101 		}
102 		else if (INVALID_GRANT.equals(errorCode)) {
103 			return new InvalidGrantException(errorMessage);
104 		}
105 		else if (INVALID_SCOPE.equals(errorCode)) {
106 			return new InvalidScopeException(errorMessage);
107 		}
108 		else if (INVALID_TOKEN.equals(errorCode)) {
109 			return new InvalidTokenException(errorMessage);
110 		}
111 		else if (INVALID_REQUEST.equals(errorCode)) {
112 			return new InvalidRequestException(errorMessage);
113 		}
114 		else if (REDIRECT_URI_MISMATCH.equals(errorCode)) {
115 			return new RedirectMismatchException(errorMessage);
116 		}
117 		else if (UNSUPPORTED_GRANT_TYPE.equals(errorCode)) {
118 			return new UnsupportedGrantTypeException(errorMessage);
119 		}
120 		else if (UNSUPPORTED_RESPONSE_TYPE.equals(errorCode)) {
121 			return new UnsupportedResponseTypeException(errorMessage);
122 		}
123 		else if (ACCESS_DENIED.equals(errorCode)) {
124 			return new UserDeniedAuthorizationException(errorMessage);
125 		}
126 		else {
127 			return new OAuth2Exception(errorMessage);
128 		}
129 	}
130 
131 	/**
132 	 * Creates an {@link OAuth2Exception} from a Map&lt;String,String&gt;.
133 	 * 
134 	 * @param errorParams
135 	 * @return
136 	 */
137 	public static OAuth2Exception valueOf(Map<String, String> errorParams) {
138 		String errorCode = errorParams.get(ERROR);
139 		String errorMessage = errorParams.containsKey(DESCRIPTION) ? errorParams.get(DESCRIPTION)
140 				: null;
141 		OAuth2Exception ex = create(errorCode, errorMessage);
142 		Set<Map.Entry<String, String>> entries = errorParams.entrySet();
143 		for (Map.Entry<String, String> entry : entries) {
144 			String key = entry.getKey();
145 			if (!ERROR.equals(key) && !DESCRIPTION.equals(key)) {
146 				ex.addAdditionalInformation(key, entry.getValue());
147 			}
148 		}
149 
150 		return ex;
151 	}
152 	
153 	@Override
154 	public String toString() {
155 		return getSummary();
156 	}
157 
158 	/**
159 	 * @return a comma-delimited list of details (key=value pairs)
160 	 */
161 	public String getSummary() {
162 		
163 		StringBuilder builder = new StringBuilder();
164 
165 		String delim = "";
166 
167 		String error = this.getOAuth2ErrorCode();
168 		if (error != null) {
169 			builder.append(delim).append("error=\"").append(error).append("\"");
170 			delim = ", ";
171 		}
172 
173 		String errorMessage = this.getMessage();
174 		if (errorMessage != null) {
175 			builder.append(delim).append("error_description=\"").append(errorMessage).append("\"");
176 			delim = ", ";
177 		}
178 
179 		Map<String, String> additionalParams = this.getAdditionalInformation();
180 		if (additionalParams != null) {
181 			for (Map.Entry<String, String> param : additionalParams.entrySet()) {
182 				builder.append(delim).append(param.getKey()).append("=\"").append(param.getValue()).append("\"");
183 				delim = ", ";
184 			}
185 		}
186 		
187 		return builder.toString();
188 
189 	}
190 }