/** * personium.io * Copyright 2014 FUJITSU LIMITED * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.fujitsu.dc.core; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import org.apache.http.HttpStatus; import com.fujitsu.dc.core.DcCoreMessageUtils.Severity; import com.fujitsu.dc.core.auth.OAuth2Helper.AcceptableAuthScheme; import com.fujitsu.dc.core.auth.OAuth2Helper.Scheme; import com.fujitsu.dc.core.exceptions.ODataErrorMessage; /** * 認証エラー(PR401-AU-xxxx)が発生した場合のログ出力クラス. */ @SuppressWarnings("serial") public final class DcCoreAuthzException extends DcCoreException { /** * 認証ヘッダが必要. */ public static final DcCoreAuthzException AUTHORIZATION_REQUIRED = create("PR401-AU-0001"); /** * トークン有効期限切れ. */ public static final DcCoreAuthzException EXPIRED_ACCESS_TOKEN = create("PR401-AU-0002"); /** * AuthenticationSchemeが無効. */ public static final DcCoreAuthzException INVALID_AUTHN_SCHEME = create("PR401-AU-0003"); /** * ベーシック認証ヘッダのフォーマットが無効. */ public static final DcCoreAuthzException BASIC_AUTH_FORMAT_ERROR = create("PR401-AU-0004"); /** * トークンパースエラー. */ public static final DcCoreAuthzException TOKEN_PARSE_ERROR = create("PR401-AU-0006"); /** * リフレッシュトークンでのアクセス. */ public static final DcCoreAuthzException ACCESS_WITH_REFRESH_TOKEN = create("PR401-AU-0007"); /** * トークン署名検証エラー. */ public static final DcCoreAuthzException TOKEN_DISG_ERROR = create("PR401-AU-0008"); /** * クッキー認証エラー. */ public static final DcCoreAuthzException COOKIE_AUTHENTICATION_FAILED = create("PR401-AU-0009"); /** * ベーシック認証エラー(Accountロック中). */ public static final DcCoreAuthzException BASIC_AUTHENTICATION_FAILED_IN_ACCOUNT_LOCK = create("PR401-AU-0010"); /** * ベーシック認証エラー. */ public static final DcCoreAuthzException BASIC_AUTHENTICATION_FAILED = create("PR401-AU-0011"); /** * インナークラスを強制的にロードする. */ public static void loadConfig() { } String realm; AcceptableAuthScheme authScheme = AcceptableAuthScheme.ALL; // デフォルトとしてBasic/Bearerを許可する設定にしておく /** * コンストラクタ. * @param status HTTPレスポンスステータス * @param severityエラーレベル * @param code エラーコード * @param message エラーメッセージ * @param error OAuth認証エラーのエラーコード * @param realm WWWW-Authenticateヘッダを返す場合はここにrealm値を設定する * @param authScheme 認証を許可するAuthSchemeの種別 */ DcCoreAuthzException(final String code, final Severity severity, final String message, final int status, final String realm, final AcceptableAuthScheme authScheme) { super(code, severity, message, status); this.realm = realm; this.authScheme = authScheme; } /** * realmを設定してオブジェクト生成. * @param realm2set realm * @return CoreAuthnException */ public DcCoreAuthzException realm(String realm2set) { // クローンを作成 return new DcCoreAuthzException(this.code, this.severity, this.message, this.status, realm2set, AcceptableAuthScheme.ALL); } /** * realmを設定してオブジェクト生成. * @param realm2set realm * @param acceptableAuthScheme 認証を許可するAuthSchemeの種別 * @return CoreAuthnException */ public DcCoreAuthzException realm(String realm2set, AcceptableAuthScheme acceptableAuthScheme) { // クローンを作成 return new DcCoreAuthzException(this.code, this.severity, this.message, this.status, realm2set, acceptableAuthScheme); } @Override public Response createResponse() { ResponseBuilder rb = Response.status(HttpStatus.SC_UNAUTHORIZED) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) .entity(new ODataErrorMessage(code, message)); // レルム値が設定されていれば、WWW-Authenticateヘッダーを返却する。 if (null != this.realm) { switch (this.authScheme) { case BEARER: rb = rb.header(HttpHeaders.WWW_AUTHENTICATE, Scheme.BEARER + " realm=\"" + this.realm + "\""); break; case BASIC: rb = rb.header(HttpHeaders.WWW_AUTHENTICATE, Scheme.BASIC + " realm=\"" + this.realm + "\""); break; default: // デフォルトとして、Bearer/Basicの両方を返却する。 rb = rb.header(HttpHeaders.WWW_AUTHENTICATE, Scheme.BEARER + " realm=\"" + this.realm + "\""); rb = rb.header(HttpHeaders.WWW_AUTHENTICATE, Scheme.BASIC + " realm=\"" + this.realm + "\""); break; } } return rb.build(); } /** * 原因例外を追加したものを作成して返します. * @param t 原因例外 * @return DcCoreException */ public DcCoreException reason(final Throwable t) { // クローンを作成して DcCoreException ret = new DcCoreAuthzException( this.code, this.severity, this.message, this.status, this.realm, this.authScheme); // スタックトレースをセット ret.setStackTrace(t.getStackTrace()); return ret; } /** * ファクトリーメソッド. * @param code DCメッセージコード * @return DcCoreException */ public static DcCoreAuthzException create(String code) { int statusCode = DcCoreException.parseCode(code); // ログレベルの取得 Severity severity = DcCoreMessageUtils.getSeverity(code); if (severity == null) { // ログレベルが設定されていなかったらレスポンスコードから自動的に判定する。 severity = decideSeverity(statusCode); } // ログメッセージの取得 String message = DcCoreMessageUtils.getMessage(code); return new DcCoreAuthzException(code, severity, message, statusCode, null, AcceptableAuthScheme.ALL); } }