import { InjectToken, ObjectMap, Type } from '@tsdi/ioc';
import { MvcContext, IContext, MvcConfiguration } from '@mvx/mvc';
import { Middleware, Context } from 'koa';
import { IStrategy } from './IStrategy';
/**
 * deserialize user interface.
 *
 * @export
 * @interface IDeserializeUser
 */
export interface IDeserializeUser {
    deserializeUser(obj: any, ctx?: IContext): Promise<any>;
}
export declare type DeserializeUserOption = Type<IDeserializeUser> | ((obj: any, ctx?: IContext) => Promise<any>);
export interface ISerializeUser {
    serializeUser(user: any, ctx: IContext): Promise<any>;
}
export declare type SerializeUserOption = Type<ISerializeUser> | ((user: any, ctx: IContext) => Promise<any>);
export interface ITransformAuthInfo {
    authInfo(info: any, ctx: IContext): Promise<any>;
}
export declare type TransformAuthInfoOption = Type<ITransformAuthInfo> | ((info: any, ctx: IContext) => Promise<any>);
export interface IAuthFlowOption {
    strategy: string | string[];
    options: AuthenticateOption;
}
/**
 * strategy option.
 *
 * @export
 * @interface IStrategyOption
 */
export interface IStrategyOption extends ObjectMap {
    strategy: string;
    name?: string;
    verify?: Function;
}
/**
 *  init auth option.
 */
export interface InitAuthOption {
    /**
     * assign deserializer user info to ctx state via this property name.
     */
    userProperty?: string;
    /**
     * assign deserializer user role to ctx state via this property name.
     */
    rolesProperty?: string;
}
export interface PassportConfigure {
    default?: IAuthFlowOption;
    /**
     * @deprecated
     */
    initialize?: InitAuthOption;
    strategies: IStrategyOption[];
    serializers?: SerializeUserOption[];
    deserializers?: DeserializeUserOption[];
    authInfos?: TransformAuthInfoOption[];
}
/**
 * authenticate option.
 *
 * @export
 * @interface AuthenticateOption
 */
export interface AuthenticateOption extends InitAuthOption, ObjectMap<any> {
    session?: boolean;
    successRedirect?: string;
    successReturnToOrRedirect?: string;
    /**
     * assign deserializer user info to ctx state via this property name.
     * @deprecated use userProperty instead.
     */
    assignProperty?: any;
    /**
     * auth faild to redirect to.
     */
    failureRedirect?: string;
    failureFlash?: string | {
        type: string;
        message: string;
    };
    failureMessage?: string | boolean;
    failWithError?: boolean;
    successFlash?: string | {
        type: string;
        message: string;
    };
    successMessage?: string | boolean;
    authInfo?: boolean;
}
export interface VaildFailure {
    challenge: string | any;
    status: number;
}
declare module '@mvx/mvc' {
    interface IConfiguration extends MvcConfiguration {
        /**
         * passports config.
         *
         * @memberof IConfiguration
         */
        passports?: PassportConfigure;
    }
}
declare module 'koa' {
    interface Context {
        /**
         * passport.
         */
        passport: IAuthenticator;
        /**
         * auth failues.
         */
        failures: VaildFailure[];
        /**
         * mvc application context.
         */
        mvcContext: MvcContext;
        connection?: any;
        /**
         * get current login user.
         */
        getUser<T = any>(): T;
        /**
         * get current login user roles.
         */
        getRoles<T = string>(): T[];
        /**
         * current login user has this roles or not.
         * @param role roles.
         */
        hasRole(...role: string[]): boolean;
        /**
         * Intiate a login session for `user`.
         *
         * Options:
         *   - `session`  Save login state in session, defaults to `true`
         *
         * Examples:
         *
         *     await req.logIn(user, { session: false });
         * @param user
         * @param options
         */
        login(user: any, options?: any): Promise<void>;
        /**
         * Intiate a login session for `user`.
         * @param user
         * @param options
         * @param done
         */
        logIn(user: any, options: any, done: any): any;
        /**
         * the current user logout.
         */
        logout(): void;
        /**
         * the current user logout.
         */
        logOut(): void;
        /**
         * Test if request is authenticated.
         */
        isAuthenticated(): boolean;
        /**
         * Test if request is unauthenticated.
         */
        isUnauthenticated(): boolean;
    }
}
/**
 * IAuthenticator token.
 */
export declare const AuthenticatorToken: InjectToken<IAuthenticator>;
/**
 * `Authenticator` constructor.
 *
 */
export interface IAuthenticator {
    /**
     * user property.
     *
     * @type {string}
     * @memberof IAuthenticator
     */
    readonly userProperty: string;
    /**
     * user roles property.
     *
     * @type {string}
     * @memberof IAuthenticator
     */
    readonly rolesProperty: string;
    /**
     * get strategy.
     *
     * @param {string} name
     * @returns {IStrategy}
     * @memberof IAuthenticator
     */
    get(name: string): IStrategy;
    /**
     * Utilize the given `strategy` with optional `name`, overridding the strategy's
     * default name.
     *
     * Examples:
     *
     *     passport.use(new TwitterStrategy(...));
     *
     *     passport.use('api', new http.BasicStrategy(...));
     *
     */
    use(strategy: IStrategy): any;
    use(name: string, strategy: IStrategy): any;
    /**
     * Un-utilize the `strategy` with given `name`.
     *
     * In typical applications, the necessary authentication strategies are static,
     * configured once and always available.  As such, there is often no need to
     * invoke this function.
     *
     * However, in certain situations, applications may need dynamically configure
     * and de-configure authentication strategies.  The `use()`/`unuse()`
     * combination satisfies these scenarios.
     *
     * Examples:
     *
     *     passport.unuse('legacy-api');
     *
     */
    unuse(name: string): this;
    /**
     * Passport's primary initialization middleware.
     *
     * Intializes Passport for incoming requests, allowing
     * authentication strategies to be applied.
     *
     * If sessions are being utilized, applications must set up Passport with
     * functions to serialize a user into and out of a session.  For example, a
     * common pattern is to serialize just the user ID into the session (due to the
     * fact that it is desirable to store the minimum amount of data in a session).
     * When a subsequent request arrives for the session, the full User object can
     * be loaded from the database by ID.
     *
     * Note that additional middleware is required to persist login state, so we
     * must use the `connect.session()` middleware _before_ `passport.initialize()`.
     *
     * If sessions are being used, this middleware must be in use by the
     * Koa application for Passport to operate.  If the application is
     * entirely stateless (not using sessions), this middleware is not necessary,
     * but its use will not have any adverse impact.
     *
     * Options:
     *   - `userProperty`  Property to set on `ctx.state` upon login, defaults to _user_
     *
     * Examples:
     *     app.use(connect.cookieParser());
     *
     *     app.use(connect.session({ secret: 'keyboard cat' }));
     *     app.use(passport.initialize());
     *     app.use(passport.initialize({ userProperty: 'currentUser' }));
     *     app.use(passport.session());
     *
     *     passport.serializeUser(function(user, done) {
     *       done(null, user.id);
     *     });
     *
     *     passport.deserializeUser(function(id, done) {
     *       User.findById(id, function (err, user) {
     *         done(err, user);
     *       });
     *     });
     *
     */
    initialize(options?: InitAuthOption): Middleware;
    /**
     * Authenticates requests.
     *
     * Applies the `name`ed strategy (or strategies) to the incoming request, in
     * order to authenticate the request.  If authentication is successful, the user
     * will be logged in and populated at `ctx.request.state.user` and a session will be
     * established by default. If authentication fails, an unauthorized response
     * will be sent.
     *
     * Options:
     *   - `session`          Save login state in session, defaults to _true_
     *   - `successRedirect`  After successful login, redirect to given URL
     *   - `failureRedirect`  After failed login, redirect to given URL
     *   - `assignProperty`   Assign the object provided by the verify callback to given property
     *
     * An optional `callback` can be supplied to allow the application to overrride
     * the default manner in which authentication attempts are handled.  The
     * callback has the following signature, where `user` will be set to the
     * authenticated user on a successful authentication attempt, or `false`
     * otherwise.  An optional `info` argument will be passed, containing additional
     * details provided by the strategy's verify callback.
     *
     *     app.get('/protected', function(ctx, next) {
     *       passport.authenticate('local', function(err, user, info) {
     *         if (err) { return next(err) }
     *         if (!user) { return ctx.redirect('/signin') }
     *         ctx.redirect('/account');
     *       })(ctx, next);
     *     });
     *
     * Note that if a callback is supplied, it becomes the application's
     * responsibility to log-in the user, establish a session, and otherwise perform
     * the desired operations.
     * Examples:
     *
     *     passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' })(ctx);
     *
     *     passport.authenticate('local', function(err, user) {
     *       if (!user) { return ctx.redirect('/login'); }
     *       ctx.end('Authenticated!');
     *     })(ctx);
     *
     *     passport.authenticate('basic', { session: false })(ctx);
     *
     *     app.get('/auth/twitter', passport.authenticate('twitter'), function(ctx) {
     *       // request will be redirected to Twitter
     *     });
     */
    authenticate(strategyNames: string | string[], callback?: (this: void, err: Error, user?: any, info?: any, status?: any) => void): Middleware;
    authenticate(strategyNames: string | string[], options: AuthenticateOption, callback?: (this: void, err: Error, user?: any, info?: any, status?: any) => void): Middleware;
    /**
     * Middleware that will authorize a third-party account using the given
     * `strategy` name, with optional `options`.
     *
     * If authorization is successful, the result provided by the strategy's verify
     * callback will be assigned to `ctx.state.account`.  The existing login session and
     * `ctx.state.user` will be unaffected.
     *
     * This function is particularly useful when connecting third-party accounts
     * to the local account of a user that is currently authenticated.
     *
     * Examples:
     *
     *    passport.authorize('twitter-authz', { failureRedirect: '/account' });
     */
    authorize(strategy: string | string[], options?: AuthenticateOption, callback?: any): Middleware;
    /**
     * Middleware that will restore login state from a session.
     *
     * Web applications typically use sessions to maintain login state between
     * requests.  For example, a user will authenticate by entering credentials into
     * a form which is submitted to the server.  If the credentials are valid, a
     * login session is established by setting a cookie containing a session
     * identifier in the user's web browser.  The web browser will send this cookie
     * in subsequent requests to the server, allowing a session to be maintained.
     *
     * If sessions are being utilized, and a login session has been established,
     * this middleware will populate `req.user` with the current user.
     *
     * Note that sessions are not strictly required for Passport to operate.
     * However, as a general rule, most web applications will make use of sessions.
     * An exception to this rule would be an API server, which expects each HTTP
     * request to provide credentials in an Authorization header.
     *
     * Examples:
     *
     *     app.use(connect.cookieParser());
     *     app.use(connect.session({ secret: 'keyboard cat' }));
     *     app.use(passport.initialize());
     *     app.use(passport.session());
     *
     * Options:
     *   - `pauseStream`      Pause the request stream before deserializing the user
     *                        object from the session.  Defaults to _false_.  Should
     *                        be set to true in cases where middleware consuming the
     *                        request body is configured after passport and the
     *                        deserializeUser method is asynchronous.
     *
     * @api public
     */
    session(options?: AuthenticateOption): Middleware;
    /**
     * Registers a function used to serialize user objects into the session.
     *
     * Examples:
     *
     *     passport.serializeUser(function(user, done) {
     *       done(null, user.id);
     *     });
     *
     * @api public
     */
    serializeUser(fn: (user: any, ctx: Context) => Promise<any>): any;
    serializeUser(user: object, ctx?: Context): Promise<any>;
    /**
     * Registers a function used to deserialize user objects out of the session.
     *
     * Examples:
     *
     *     passport.deserializeUser(function(id, done) {
     *       User.findById(id, function (err, user) {
     *         done(err, user);
     *       });
     *     });
     *
     * @api public
     */
    deserializeUser(fn: (obj: any, ctx: Context) => Promise<any>): any;
    deserializeUser(obj: any, ctx?: Context): Promise<any>;
    /**
     * Registers a function used to transform auth info.
     *
     * In some circumstances authorization details are contained in authentication
     * credentials or loaded as part of verification.
     *
     * For example, when using bearer tokens for API authentication, the tokens may
     * encode (either directly or indirectly in a database), details such as scope
     * of access or the client to which the token was issued.
     *
     * Such authorization details should be enforced separately from authentication.
     * Because Passport deals only with the latter, this is the responsiblity of
     * middleware or routes further along the chain.  However, it is not optimal to
     * decode the same data or execute the same database query later.  To avoid
     * this, Passport accepts optional `info` along with the authenticated `user`
     * in a strategy's `success()` action.  This info is set at `req.authInfo`,
     * where said later middlware or routes can access it.
     *
     * Optionally, applications can register transforms to proccess this info,
     * which take effect prior to `req.authInfo` being set.  This is useful, for
     * example, when the info contains a client ID.  The transform can load the
     * client from the database and include the instance in the transformed info,
     * allowing the full set of client properties to be convieniently accessed.
     *
     * If no transforms are registered, `info` supplied by the strategy will be left
     * unmodified.
     *
     * Examples:
     *
     *     passport.transformAuthInfo(function(info, done) {
     *       Client.findById(info.clientID, function (err, client) {
     *         info.client = client;
     *         done(err, info);
     *       });
     *     });
     *
     * @api public
     */
    transformAuthInfo(fn: (info: any, ctx: Context) => Promise<any>): void;
    transformAuthInfo(info: {
        type: string;
        message: string;
    }, ctx: Context): any;
}
