Necko:nsIAuthPrompt2: Difference between revisions

update per final changes
No edit summary
(update per final changes)
 
(24 intermediate revisions by the same user not shown)
Line 8: Line 8:
The interfaces in question are nsIAuthPrompt and nsIPromptService; possibly nsIPrompt as well.
The interfaces in question are nsIAuthPrompt and nsIPromptService; possibly nsIPrompt as well.


I'll suggest an nsIAuthPrompt2 interface below. Its methods will have counterparts in nsIPromptService2; they will have the same signature but an addition window argument.
I'll suggest an nsIAuthPrompt2 interface below. Its methods will have counterparts in nsIPromptService2; they will have the same signature but an additional window argument.


The nsIAuthPrompt2 is what necko calls stuff on; nsIPromptService2 is what embeddors would implement.
The nsIAuthPrompt2 is what necko calls stuff on; nsIPromptService2 is what embeddors would implement.


This suggestion is based on https://bugzilla.mozilla.org/attachment.cgi?id=163161 but slightly modified.
This suggestion is based on https://bugzilla.mozilla.org/attachment.cgi?id=163161 but slightly modified, and async calls added.


/**
* A object that hold authentication information. The caller of
* nsIAuthPrompt2::promptUsernameAndPassword or
* nsIAuthPrompt2::promptPasswordAsync provides an object implementing this
* interface; the prompt implementation can then read the values here to prefill
* the dialog. After the user entered the authentication information, it should
* set the attributes of this object to indicate to the caller what was entered
* by the user.
*/
[scriptable, uuid(0d73639c-2a92-4518-9f92-28f71fea5f20)]
interface nsIAuthInformation : nsISupports
{
  /** @name Flags */
  /* @{ */
  /**
  * This dialog belongs to a network host.
  */
  const PRUint32 AUTH_HOST = 1;
  /**
  * This dialog belongs to a proxy.
  */
  const PRUint32 AUTH_PROXY = 2;
  /**
  * This dialog needs domain information. The user interface should show a
  * domain field, prefilled with the domain attribute's value.
  */
  const PRUint32 NEED_DOMAIN = 4;
  /**
  * This dialog only asks for password information. The implementation SHOULD
  * NOT show a username field. It MUST NOT modify the user attribute,
  * although it should show its initial value to the user in some form. For
  * example, a paragraph in the dialog might say "Please enter your password
  * for user jsmith at server intranet".
  *
  * This flag is mutually exclusive with #NEED_DOMAIN.
  */
  const PRUint32 ONLY_PASSWORD = 8;
  /* @} */
  /**
  * Flags describing this dialog. A bitwise OR of the flag values
  * above.
  *
  * It is possible that neither #AUTH_HOST nor #AUTH_PROXY are set.
  *
  * Implementations should ignore flags they don't understand; especially, they
  * should not throw an exception because of an unsupported flag.
  */
  readonly attribute unsigned long flags;
  /**
  * The server-supplied realm of the authentication as defined in RFC 2617.
  * Can be the empty string if the protocol does not support realms.
  * Otherwise, this is a human-readable string like "Secret files".
  */
  readonly attribute AString realm;
  /**
  * The authentication scheme used for this request, if applicable. If the
  * protocol for this authentication does not support schemes, this will be
  * the empty string. Otherwise, this will be a string such as "basic" or
  * "digest". This string will always be in lowercase.
  */
  readonly attribute AUTF8String authenticationScheme;
  /**
  * The initial value should be used to prefill the dialog.
  * Implementations should not show the password in clear.
  * On return, this parameter should contain the username entered by
  * the user.
  */
  attribute AString username;
  /**
  * The initial value should be used to prefill the dialog or show it
  * in some other way to the user.
  * On return, this parameter should contain the username entered by
  * the user.
  */
  attribute AString password;
  /**
  * The initial value should be used to prefill the dialog or show it
  * in some other way to the user.
  * On return, this parameter should contain the domain entered by
  * the user.
  * This attribute is only used if flags include #NEED_DOMAIN.
  */
  attribute AString domain;
};
/**
* Interface for callback methods for the asynchronous nsIAuthPrompt2 method.
* Callers MUST call exactly one method if nsIAuthPrompt2::promptPasswordAsync
* returns successfully. They MUST NOT call any method on this interface before
* promptPasswordAsync returns.
*/
[scriptable, uuid(bdc387d7-2d29-4cac-92f1-dd75d786631d)]
interface nsIAuthPromptCallback : nsISupports
{
  /**
  * Authentication information is available.
  *
  * @param aContext
  *        The context as passed to promptPasswordAsync
  * @param aAuthInfo
  *        Authentication information. Must be the same object that was passed
  *        to promptPasswordAsync.
  *
  * @note  Any exceptions thrown from this method should be ignored.
  */
  void onAuthAvailable(in nsISupports aContext,
                      in nsIAuthInformation aAuthInfo);
  /**
  * Notification that the prompt was cancelled.
  *
  * @param aContext
  *        The context that was passed to promptPasswordAsync.
  * @param userCancel
  *        If false, this prompt was cancelled by calling the
  *        the cancel method on the nsICancelable; otherwise,
  *        it was cancelled by the user.
  */
  void onAuthCancelled(in nsISupports aContext, in boolean userCancel);
};
/**
* An interface allowing to prompt for a username and password. This interface
* is usually acquired using getInterface on notification callbacks or similar.
* It can be used to prompt users for authentication information, either
* synchronously or asynchronously.
*/
[scriptable, uuid(447fc780-1d28-412a-91a1-466d48129c65)]
  interface nsIAuthPrompt2 : nsISupports
  interface nsIAuthPrompt2 : nsISupports
  {         
  {         
    const PRUint32 SAVE_PASSWORD_NEVER            = 0;
  /** @name Security Levels */
    const PRUint32 SAVE_PASSWORD_FOR_SESSION      = 1;
  /* @{ */
    const PRUint32 SAVE_PASSWORD_PERMANENTLY      = 2;
  /**
  * The password will be sent unencrypted. No security provided.
  */
  const PRUint32 LEVEL_NONE = 0;
  /**
  * Password will be sent encrypted, but the connection is otherwise
  * insecure.
  */
  const PRUint32 LEVEL_PW_ENCRYPTED = 1;
  /**
  * The connection, both for password and data, is secure.
  */
  const PRUint32 LEVEL_SECURE = 2;
  /* @} */


    /** @name Security Levels */
  /**
    /* @{ */
  * Requests a username and a password. Implementations will commonly show a
    /**
  * dialog with a username and password field, depending on flags also a
    * The password will be sent unencrypted. No security provided.
  * domain field.
    */
  *
    const PRUint32 LEVEL_NONE = 0;
  * @param aChannel
    /**
  *       The channel that requires authentication.
    * Password will be sent encrypted, but the connection is otherwise
  * @param level
    * insecure.
  *        One of the level constants from above. See there for descriptions
    */
  *       of the levels.
    const PRUint32 LEVEL_PW_ENCRYPTED = 1;
  * @param authInfo
    /**
  *       Authentication information object. The implementation should fill in
    * The connection, both for password and data, is secure.
  *       this object with the information entered by the user before
    */
  *       returning.
    const PRUint32 LEVEL_SECURE = 2;
  *
    /* @} */
  * @retval true
  *         Authentication can proceed using the values in the authInfo
  *         object.
  * @retval false
  *        Authentication should be cancelled, usually because the user did
  *        not provide username/password.
  *
  * @note  Exceptions thrown from this function will be treated like a
  *         return value of false.
  */
  boolean promptAuth(in nsIChannel aChannel,
                    in PRUint32 level,
                    in nsIAuthInformation authInfo);


    /** @name Flags */
  /**
    /* @{ */
  * Asynchronously prompt the user for a username and password.
    /**
  * This has largely the same semantics as promptUsernameAndPassword(),
    * This dialog belongs to a network host.
  * but must return immediately after calling and return the entered
    */
  * data in a callback.
    const PRUint32 AUTH_HOST = 0;
  *
    /**
  * If the user closes the dialog using a cancel button or similar,
    * This dialog belongs to a proxy.
  * the callback's nsIAuthPromptCallback::onAuthCancelled method must be
    */
  * called.
    const PRUint32 AUTH_PROXY = 1;
  * Calling nsICancelable::cancel on the returned object SHOULD close the
  * dialog and MUST call nsIAuthPromptCallback::onAuthCancelled on the provided
  * callback.
  *
  * @throw NS_ERROR_NOT_IMPLEMENTED
  *       Asynchronous authentication prompts are not supported;
  *        the caller should fall back to promptUsernameAndPassword().
  */
  nsICancelable asyncPromptAuth(in nsIChannel aChannel,
                                in nsIAuthPromptCallback aCallback,
                                in nsISupports aContext,
                                in PRUint32 level,
                                in nsIAuthInformation authInfo);
};


    /**
    * This dialog needs domain information. The user interface should show a
    * domain field, prefilled with the aDomain paramter's value.
    */
    const PRUint32 NEED_DOMAIN = 2;


    /**
    * This dialog only asks for password information. The implementation SHOULD
    * NOT show a username field. It MUST NOT modify the user inout parameter,
    * although it should show its initial value to the user in some form. For
    * example, a paragraph in the dialog might say "Please enter your password
    * for user jsmith at server intranet".
    *
    * This flag is mutually exclusive with NEED_DOMAIN.
    */
    const PRUint32 ONLY_PASSWORD = 4;
    /* @} */


    /**
    * Requests a username and a password. Implementations will commonly show a
    * dialog with a username and password field, depending on flags also a
    * domain field.
    *
    * @param aChannel
    *        The channel that requires authentication.
    * @param passwordRealm
    *        The server-supplied realm for the password. This is a
    *        human-readable string like "Secret files".
    * @param level
    *        One of the level constants from above. See there for descriptions
    *        of the levels.
    * @param savePassword
    *        Hint to the implementation whether to allow saving a password and
    *        for which duration. See above for descriptions of the values.
    * @param flags
    *        Flags describing this dialog. A bitwise OR of the flag values
    *        above.
    * @param user
    *        The initial value should be used to prefill the dialog.
    *        Implementations should not show the password in clear.
    *        On return, this parameter should contain the username entered by
    *        the user.
    * @param pwd
    *        The initial value should be used to prefill the dialog or show it
    *        in some other way to the user.
    *        On return, this parameter should contain the username entered by
    *        the user.
    * @param domain
    *        The initial value should be used to prefill the dialog or show it
    *        in some other way to the user.
    *        On return, this parameter should contain the domain entered by
    *        the user.
    *        This parameter is only used if flags include AUTH_DOMAIN.
    *
    * @retval true
    *        Authentication can proceed using the values of the out
    *        parameters.
    * @retval false
    *        Authentication should be cancelled, usually because the user did
    *        not provide username/password.
    *
    * @note  Exceptions thrown from this function will be treated like a
    *        return value of false.
    */
    boolean promptUsernameAndPassword(in nsIChannel aChannel,
                                      in AString passwordRealm,
                                      in PRUint32 level,
                                      in PRUint32 savePassword,
                                      in PRUint32 flags,
                                      inout AString user,
                                      inout AString pwd,
                                      inout AString domain);


== Issues ==
* NSS/PSM wants to prompt for passwords as well, and has no nsIChannel available
** http://lxr.mozilla.org/seamonkey/source/security/manager/ssl/src/nsNSSCallbacks.cpp#188
** Make aChannel an nsISupports, which can also be a certificate or certificate store or whatever?
** However, after thinking more about this, I don't think it makes sense for this interface to be used by PSM. PSM has no use for a user or a domain, the "levels" here are not useful for it, and dialogs for certificate stores will probably look quite different. It should have its own interface.
* Use nsIRequest instead of nsIChannel?
** SOCKS authentication on a raw socket might be a use case
** But nsIRequest has no obvious place to get something remotely URI-like
* The parameter lists are quite long; group some of the info together on an object? This object could be passed to both functions.
** It would fix this error: ../../../../../mozilla/netwerk/base/public/nsIAuthPrompt2.idl:106: Error: [domstring], [utf8string], [cstring], [astring] types cannot be used as inout parameters
** switched to that in the interfaces above
* mention threads in the docs
* what's "LEVEL_SECURE"?
* maybe nsIAuthInformation could have a parameter filled on return for how long to allow caching of auth info
== Reasonings ==
This lists some reasons for why some parts of the interface look like they do
* nsIChannel as opposed to nsIURI allows inspecting the securityInfo of the channel to determine the quality of the SSL encryption
* Added authenticationScheme (RFC 2617 wording) to nsIAuthInformation to provide more information to the impl (they can always ignore the field if they don't care). this will be basic, digest, etc.
** The level is still useful, for SSL and for not requiring the impl to understand all possible schemes, and also for non-HTTP protocols
= Wallet/Satchel =
These want to add a checkbox to the dialog. I propose an interface like this:
/**
  * This interface allows creating auth prompts that have a specific parent.
  */
[scriptable, uuid(...)]
interface nsIPromptFactory
{
  /**
  * Returns an object implementing the specified interface that creates
  * prompts parented to aParent.
  */
  void getPrompt(in nsIDOMWindow aParent, in nsIIDRef iid,
                [iid_is(iid),retval] out nsQIResult result);
  };
  };


Issues:
This allows more flexibility than the current interface that wraps an nsIPrompt.
* NSS wants to prompt for passwords as well, and has no nsIChannel available
 
** Make aChannel an nsISupports, which can also be a certificate or certificate store or whatever?
For actually adding the checkbox, nsIPromptService2 will need a method like promptUsernameAndPassword2Checkbox (I decided on naming it promptAuth)
* Gnome wants asynchronous password prompts
** Provide a *async variant, taking a callback?
Confirmed users
195

edits