1d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru/*
2d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Copyright (C) 2011 The Android Open Source Project
3d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru *
4d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Licensed under the Apache License, Version 2.0 (the "License");
5d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * you may not use this file except in compliance with the License.
6d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * You may obtain a copy of the License at
7d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru *
8d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru *      http://www.apache.org/licenses/LICENSE-2.0
9d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru *
10d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software
11d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS,
12d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * See the License for the specific language governing permissions and
14d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * limitations under the License.
15d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru */
16d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
17d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Querupackage com.android.volley.toolbox;
18d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
19d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport com.android.volley.AuthFailureError;
20d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
21d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.accounts.Account;
22d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.accounts.AccountManager;
23d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.accounts.AccountManagerFuture;
24d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.content.Context;
25d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.content.Intent;
26d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport android.os.Bundle;
27d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
28d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru/**
29d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * An Authenticator that uses {@link AccountManager} to get auth
30d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * tokens of a specified type for a specified account.
31d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru */
32d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Querupublic class AndroidAuthenticator implements Authenticator {
336c9de79451d6f9410c006e4b17d3d07fae12b273Ficus Kirkpatrick    private final AccountManager mAccountManager;
34d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    private final Account mAccount;
35d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    private final String mAuthTokenType;
362ff999381ba84f38218545430768949df7bbb001Evan Charlton    private final boolean mNotifyAuthFailure;
37d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
38d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    /**
39d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     * Creates a new authenticator.
40d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     * @param context Context for accessing AccountManager
41d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     * @param account Account to authenticate as
42d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     * @param authTokenType Auth token type passed to AccountManager
43d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     */
44d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public AndroidAuthenticator(Context context, Account account, String authTokenType) {
452ff999381ba84f38218545430768949df7bbb001Evan Charlton        this(context, account, authTokenType, false);
462ff999381ba84f38218545430768949df7bbb001Evan Charlton    }
472ff999381ba84f38218545430768949df7bbb001Evan Charlton
482ff999381ba84f38218545430768949df7bbb001Evan Charlton    /**
492ff999381ba84f38218545430768949df7bbb001Evan Charlton     * Creates a new authenticator.
502ff999381ba84f38218545430768949df7bbb001Evan Charlton     * @param context Context for accessing AccountManager
512ff999381ba84f38218545430768949df7bbb001Evan Charlton     * @param account Account to authenticate as
522ff999381ba84f38218545430768949df7bbb001Evan Charlton     * @param authTokenType Auth token type passed to AccountManager
532ff999381ba84f38218545430768949df7bbb001Evan Charlton     * @param notifyAuthFailure Whether to raise a notification upon auth failure
542ff999381ba84f38218545430768949df7bbb001Evan Charlton     */
552ff999381ba84f38218545430768949df7bbb001Evan Charlton    public AndroidAuthenticator(Context context, Account account, String authTokenType,
562ff999381ba84f38218545430768949df7bbb001Evan Charlton            boolean notifyAuthFailure) {
576c9de79451d6f9410c006e4b17d3d07fae12b273Ficus Kirkpatrick        this(AccountManager.get(context), account, authTokenType, notifyAuthFailure);
586c9de79451d6f9410c006e4b17d3d07fae12b273Ficus Kirkpatrick    }
596c9de79451d6f9410c006e4b17d3d07fae12b273Ficus Kirkpatrick
606c9de79451d6f9410c006e4b17d3d07fae12b273Ficus Kirkpatrick    // Visible for testing. Allows injection of a mock AccountManager.
616c9de79451d6f9410c006e4b17d3d07fae12b273Ficus Kirkpatrick    AndroidAuthenticator(AccountManager accountManager, Account account,
626c9de79451d6f9410c006e4b17d3d07fae12b273Ficus Kirkpatrick            String authTokenType, boolean notifyAuthFailure) {
636c9de79451d6f9410c006e4b17d3d07fae12b273Ficus Kirkpatrick        mAccountManager = accountManager;
64d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        mAccount = account;
65d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        mAuthTokenType = authTokenType;
662ff999381ba84f38218545430768949df7bbb001Evan Charlton        mNotifyAuthFailure = notifyAuthFailure;
67d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
68d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
69d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    /**
70d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     * Returns the Account being used by this authenticator.
71d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru     */
72d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public Account getAccount() {
73d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        return mAccount;
74d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
75d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
767721ae67daf0231d57669c43a6e666d8c052c5bboleksii stepanian    /**
777721ae67daf0231d57669c43a6e666d8c052c5bboleksii stepanian     * Returns the Auth Token Type used by this authenticator.
787721ae67daf0231d57669c43a6e666d8c052c5bboleksii stepanian     */
797721ae67daf0231d57669c43a6e666d8c052c5bboleksii stepanian    public String getAuthTokenType() {
807721ae67daf0231d57669c43a6e666d8c052c5bboleksii stepanian        return mAuthTokenType;
817721ae67daf0231d57669c43a6e666d8c052c5bboleksii stepanian    }
827721ae67daf0231d57669c43a6e666d8c052c5bboleksii stepanian
8335d5cc345a7bc5c7391aeda3d3fce711c6376c7bFicus Kirkpatrick    // TODO: Figure out what to do about notifyAuthFailure
8435d5cc345a7bc5c7391aeda3d3fce711c6376c7bFicus Kirkpatrick    @SuppressWarnings("deprecation")
85d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    @Override
86d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public String getAuthToken() throws AuthFailureError {
876c9de79451d6f9410c006e4b17d3d07fae12b273Ficus Kirkpatrick        AccountManagerFuture<Bundle> future = mAccountManager.getAuthToken(mAccount,
882ff999381ba84f38218545430768949df7bbb001Evan Charlton                mAuthTokenType, mNotifyAuthFailure, null, null);
89d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        Bundle result;
90d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        try {
91d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            result = future.getResult();
92d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        } catch (Exception e) {
93d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            throw new AuthFailureError("Error while retrieving auth token", e);
94d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        }
95d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        String authToken = null;
96d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        if (future.isDone() && !future.isCancelled()) {
97d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            if (result.containsKey(AccountManager.KEY_INTENT)) {
98d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru                Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
99d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru                throw new AuthFailureError(intent);
100d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            }
101d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
102d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        }
103d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        if (authToken == null) {
104d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru            throw new AuthFailureError("Got null auth token for type: " + mAuthTokenType);
105d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        }
106d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
107d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        return authToken;
108d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
109d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
110d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    @Override
111d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public void invalidateAuthToken(String authToken) {
1126c9de79451d6f9410c006e4b17d3d07fae12b273Ficus Kirkpatrick        mAccountManager.invalidateAuthToken(mAccount.type, authToken);
113d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
114d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru}
115