001/* 002 * Copyright 2012-2016 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 java.security.GeneralSecurityException; 021 022 023/** 024 * This class defines an API that must be implemented by extensions which will 025 * handle incoming SCIM requests with OAuth 2.0 bearer token authentication. 026 * The OAuthTokenHandler is responsible for decoding the bearer token and 027 * checking it for authenticity and validity. 028 * <BR><BR> 029 * OAuth provides a method for clients to access a protected resource on 030 * behalf of a resource owner. In the general case, before a client can 031 * access a protected resource, it must first obtain an authorization 032 * grant from the resource owner and then exchange the authorization 033 * grant for an access token. The access token represents the grant's 034 * scope, duration, and other attributes specified by the authorization 035 * grant. The client accesses the protected resource by presenting the 036 * access token to the resource server (i.e. the Identity Data Store or Identity 037 * Proxy with the SCIM HTTP Servlet enabled). 038 * <BR><BR> 039 * The access token provides an abstraction, replacing different 040 * authorization constructs (e.g., username and password, assertion) for 041 * a single token understood by the resource server. This abstraction 042 * enables issuing access tokens valid for a short time period, as well 043 * as removing the resource server's need to understand a wide range of 044 * authentication schemes. See "OAuth 2.0 Authorization Framework: Bearer 045 * Token Usage" (<i>RFC 6750</i>) for the full 046 * specification and details. 047 * <BR><BR> 048 * TLS security is required to use OAuth 2.0 bearer tokens, as specified in 049 * <i>RFC 6750</i>. A bearer token may be used by any party 050 * in possession of that token (the "bearer"), and thus needs to be protected 051 * when transmitted across the network. Implementations of this API should take 052 * special care to verify that the token came from a trusted source (using a 053 * secret key or some other signing mechanism to prove that the token is 054 * authentic). Please read "OAuth 2.0 Threat Model and Security Considerations" 055 * (<i>RFC 6819</i>) for a comprehensive list of 056 * security threats to consider when working with OAuth bearer tokens. 057 * <BR><BR> 058 * The OAuthTokenHandler is also responsible for extracting an authorization DN 059 * from the bearer token (or otherwise providing one), which will be used to 060 * apply access controls before returning the protected resource. There are also 061 * methods to extract the expiration date of the token as well as verify that 062 * the intended audience is this server (to deal with token redirect). 063 * <BR><BR> 064 * The order these methods are called by the SCIM HTTP Servlet Extension is as 065 * follows: 066 * <ol> 067 * <li><i>decodeOAuthToken()</i></li> 068 * <li><i>isTokenAuthentic()</i></li> 069 * <li><i>isTokenForThisServer()</i></li> 070 * <li><i>isTokenExpired()</i></li> 071 * <li><i>validateToken()</i></li> 072 * <li><i>getAuthzDN()</i></li> 073 * </ol> 074 * If any of the methods fail or return an error result, the server will return 075 * an appropriate "unauthorized" response to the client. 076 */ 077public interface OAuthTokenHandler 078{ 079 /** 080 * Creates an {@link OAuthToken} instance from the incoming token value. 081 * <p> 082 * Implementers may choose to return a subclass of {@link OAuthToken} in 083 * order to provide convenience methods for interacting with the token. This 084 * can be helpful because the returned {@link OAuthToken} is passed to all of 085 * the other methods in this class. 086 * 087 * @param rawTokenValue the b64token token value. Note that b64token is just 088 * an ABNF syntax definition and does not imply any 089 * base64-encoding of the token value. 090 * @return a {@link OAuthToken} instance. This must not be {@code null}. 091 * @throws GeneralSecurityException if there is an error decoding the token 092 */ 093 OAuthToken decodeOAuthToken(final String rawTokenValue) 094 throws GeneralSecurityException; 095 096 097 098 /** 099 * Determines whether the given token is expired. 100 * 101 * @param token the OAuth 2.0 bearer token. 102 * @return {@code true} if the token is already expired, {@code false} if not. 103 * @throws GeneralSecurityException if there is an error determining the 104 * token's expiration date 105 */ 106 boolean isTokenExpired(final OAuthToken token) 107 throws GeneralSecurityException; 108 109 110 111 /** 112 * Determines whether the incoming token is authentic (i.e. that it came from 113 * a trusted authorization server and not an attacker). Implementers are 114 * encouraged to use signed tokens and use this method to verify the 115 * signature, but other methods such as symmetric key encryption (using a 116 * shared secret) can be used as well. 117 * 118 * @param token the OAuth 2.0 bearer token. 119 * @return {@code true} if the bearer token can be verified as authentic and 120 * originating from a trusted source, {@code false} if not. 121 * @throws GeneralSecurityException if there is an error determining whether 122 * the token is authentic 123 */ 124 boolean isTokenAuthentic(final OAuthToken token) 125 throws GeneralSecurityException; 126 127 128 129 /** 130 * Determines whether the incoming token is targeted for this server. This 131 * allows the implementation to reject the token early in the validation 132 * process if it can see that the intended recipient was not this server. 133 * 134 * @param token the OAuth 2.0 bearer token. 135 * @return {@code true} if the bearer token identifies this server as the 136 * intended recipient, {@code false} if not. 137 * @throws GeneralSecurityException if there is an error determining whether 138 * the token is for this server 139 */ 140 boolean isTokenForThisServer(final OAuthToken token) 141 throws GeneralSecurityException; 142 143 144 145 /** 146 * Determines whether the incoming token is valid for the given request. This 147 * method should verify that the token is legitimate and grants access to the 148 * requested resource specified in the {@link SCIMRequest}. This typically 149 * involves checking the token scope and any other attributes granted by the 150 * authorization grant. Implementations may need to call back to the 151 * authorization server to verify that the token is still valid and has not 152 * been revoked. 153 * 154 * @param token the OAuth 2.0 bearer token. 155 * @param scimRequest the {@link SCIMRequest} that we are validating. 156 * @return an {@link OAuthTokenStatus} object which indicates whether the 157 * bearer token is valid and grants access to the target resource. 158 * This must not be {@code null}. 159 * @throws GeneralSecurityException if there is an error determining whether 160 * the token is valid 161 */ 162 OAuthTokenStatus validateToken(final OAuthToken token, 163 final SCIMRequest scimRequest) 164 throws GeneralSecurityException; 165 166 167 168 /** 169 * Extracts the DN of the authorization entry (for which to apply access 170 * controls) from the incoming token. 171 * <p> 172 * This may require performing an LDAP search in order to find the DN that 173 * matches a certain attribute value contained in the token. 174 * 175 * @param token the OAuth 2.0 bearer token. 176 * @return the authorization DN to use. This must not return {@code null}. 177 * @throws GeneralSecurityException if there is an error determining the 178 * authorization user DN 179 */ 180 String getAuthzDN(final OAuthToken token) throws GeneralSecurityException; 181}