View Javadoc
1   /*
2    * Copyright 2008-2009 Web Cohesion, Andrew McCall
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.security.oauth.provider.filter;
18  
19  import org.springframework.security.core.AuthenticationException;
20  import org.springframework.security.core.context.SecurityContextHolder;
21  import org.springframework.security.oauth.common.OAuthCodec;
22  import org.springframework.security.oauth.common.OAuthConsumerParameter;
23  import org.springframework.security.oauth.common.OAuthProviderParameter;
24  import org.springframework.security.oauth.provider.ConsumerAuthentication;
25  import org.springframework.security.oauth.provider.ConsumerDetails;
26  import org.springframework.security.oauth.provider.InvalidOAuthParametersException;
27  import org.springframework.security.oauth.provider.token.OAuthProviderToken;
28  
29  import javax.servlet.FilterChain;
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  import java.io.IOException;
33  import java.util.Map;
34  
35  /**
36   * Processing filter for handling a request for an OAuth token. The default implementation assumes a request for a new
37   * unauthenticated request token. The default {@link #setFilterProcessesUrl(String) processes URL} is "/oauth_request_token".
38   *
39   * @author Ryan Heaton
40   * @author Andrew McCall
41   */
42  public class UnauthenticatedRequestTokenProcessingFilter extends OAuthProviderProcessingFilter {
43  
44    // The OAuth spec doesn't specify a content-type of the response.  However, it's NOT
45    // "application/x-www-form-urlencoded" because the response isn't URL-encoded. Until
46    // something is specified, we'll assume that it's just "text/plain".
47    private String responseContentType = "text/plain;charset=utf-8";
48  
49    private boolean require10a = true;
50  
51    public UnauthenticatedRequestTokenProcessingFilter() {
52      setFilterProcessesUrl("/oauth_request_token");
53    }
54  
55    @Override
56    protected void validateAdditionalParameters(ConsumerDetails consumerDetails, Map<String, String> oauthParams) {
57      super.validateAdditionalParameters(consumerDetails, oauthParams);
58  
59      if (isRequire10a()) {
60        String token = oauthParams.get(OAuthConsumerParameter.oauth_callback.toString());
61        if (token == null) {
62          throw new InvalidOAuthParametersException(messages.getMessage("AccessTokenProcessingFilter.missingCallback", "Missing callback."));
63        }
64      }
65    }
66  
67    protected void onValidSignature(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException {
68      //signature is verified; create the token, send the response.
69      ConsumerAuthenticationringframework/security/oauth/provider/ConsumerAuthentication.html#ConsumerAuthentication">ConsumerAuthentication authentication = (ConsumerAuthentication) SecurityContextHolder.getContext().getAuthentication();
70      OAuthProviderToken authToken = createOAuthToken(authentication);
71      if (!authToken.getConsumerKey().equals(authentication.getConsumerDetails().getConsumerKey())) {
72        throw new IllegalStateException("The consumer key associated with the created auth token is not valid for the authenticated consumer.");
73      }
74  
75      String tokenValue = authToken.getValue();
76      String callback = authentication.getOAuthParameters().get(OAuthConsumerParameter.oauth_callback.toString());
77  
78      StringBuilder responseValue = new StringBuilder(OAuthProviderParameter.oauth_token.toString())
79        .append('=')
80        .append(OAuthCodec.oauthEncode(tokenValue))
81        .append('&')
82        .append(OAuthProviderParameter.oauth_token_secret.toString())
83        .append('=')
84        .append(OAuthCodec.oauthEncode(authToken.getSecret()));
85      if (callback != null) {
86        responseValue.append('&')
87          .append(OAuthProviderParameter.oauth_callback_confirmed.toString())
88          .append("=true");
89      }
90      response.setContentType(getResponseContentType());
91      response.getWriter().print(responseValue.toString());
92      response.flushBuffer();
93    }
94  
95    @Override
96    protected void onNewTimestamp() throws AuthenticationException {
97      //no-op. A new timestamp should be supplied for a request for a new unauthenticated request token.
98    }
99  
100   /**
101    * Create the OAuth token for the specified consumer key.
102    *
103    * @param authentication The authentication request.
104    * @return The OAuth token.
105    */
106   protected OAuthProviderToken createOAuthToken(ConsumerAuthentication authentication) {
107     return getTokenServices().createUnauthorizedRequestToken(authentication.getConsumerDetails().getConsumerKey(),
108                                                              authentication.getOAuthParameters().get(OAuthConsumerParameter.oauth_callback.toString()));
109   }
110 
111   /**
112    * The content type of the response.
113    *
114    * @return The content type of the response.
115    */
116   public String getResponseContentType() {
117     return responseContentType;
118   }
119 
120   /**
121    * The content type of the response.
122    *
123    * @param responseContentType The content type of the response.
124    */
125   public void setResponseContentType(String responseContentType) {
126     this.responseContentType = responseContentType;
127   }
128 
129   /**
130    * Whether to require 1.0a support.
131    *
132    * @return Whether to require 1.0a support.
133    */
134   public boolean isRequire10a() {
135     return require10a;
136   }
137 
138   /**
139    * Whether to require 1.0a support.
140    *
141    * @param require10a Whether to require 1.0a support.
142    */
143   public void setRequire10a(boolean require10a) {
144     this.require10a = require10a;
145   }
146 }