JDK-8275529 : Alternate Subject.getSubject and doAs APIs that do not depend on Security Manager APIs
  • Type: CSR
  • Component: security-libs
  • Sub-Component: javax.security
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 18
  • Submitted: 2021-10-19
  • Updated: 2021-11-29
  • Resolved: 2021-11-04
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Create new JAAS APIs to be replacements of deprecated `getSubject` and `doAs`.

Problem
-------

With JEP 411, we have deprecated most APIs related to the security manager. In JDK 17, we already deprecated `Subject::getSubject` because its argument is a deprecated class `AccessControlContext`. In JDK 18, we will deprecate the `Subject::doAs` methods because they are closely related to `getSubject()` (one setter one getter) and their specifications heavily depend on deprecated classes `AccessController` and `SubjectDomainCombiner`. However, these APIs are useful independent of the Security Manager as they provide a mechanism
to transport a Subject's credentials across API boundaries. Thus, we need to create new APIs that do not depend on the Security Manager APIs -- this plan was already documented in JEP 411.

Solution
--------

Deprecate `Subject::doAs` for removal and add new methods `Subject::current` and `Subject::callAs`. The new APIs do not have API dependencies on the deprecated Security Manager APIs and are designed to offer the same capabilities as the deprecated APIs.

Specification
-------------

     package javax.security.auth;
     
    
     public final class Subject implements java.io.Serializable {
    
         /**
          * Get the {@code Subject} associated with the provided
          * {@code AccessControlContext}.
          ....
          * @deprecated This method depends on {@link AccessControlContext}
          *       which, in conjunction with
          *       {@linkplain SecurityManager the Security Manager}, is deprecated
    -     *       and subject to removal in a future release. However, obtaining a
    -     *       Subject is useful independent of the Security Manager, so a
    -     *       replacement for this method may be added in a future release.
    +     *       and subject to removal in a future release. However,
    +     *       obtaining a Subject is useful independent of the Security Manager.
    +     *       Thus, a replacement API named {@link #current()} has been added
    +     *       which can be used to obtain the current subject.

          */
         @Deprecated(since="17", forRemoval=true)
         public static Subject getSubject(final AccessControlContext acc);
    +
    +    /**
    +     * Returns the current subject.
    +     * <p>
    +     * The current subject is installed by the {@link #callAs} method.
    +     * When {@code callAs(subject, action)} is called, {@code action} is
    +     * executed with {@code subject} as its current subject which can be
    +     * retrieved by this method. After {@code action} is finished, the current
    +     * subject is reset to its previous value. The current
    +     * subject is {@code null} before the first call of {@code callAs()}.
    +     * <p>
    +     * When a new thread is created, its current subject is the same as
    +     * the one of its parent thread, and will not change even if
    +     * its parent thread's current subject is changed to another value.
    +     *
    +     * @implNote
    +     * By default, this method returns the same value as
    +     * {@code Subject.getSubject(AccessController.getContext())}. This
    +     * preserves compatibility with code that may still be calling {@code doAs}
    +     * which installs the subject in an {@code AccessControlContext}. However,
    +     * if the system property {@systemProperty jdk.security.auth.subject.useTL}
    +     * is set to {@code true}, the subject is retrieved from an inheritable
    +     * {@code ThreadLocal} object. This behavior is subject to
    +     * change in a future version.
    +     *
    +     * @return the current subject, or {@code null} if a current subject is
    +     *      not installed or the current subject is set to {@code null}.
    +     * @see #callAs(Subject, Callable)
    +     * @since 18
    +     */
    +    public static Subject current();
    
    +    /**
    +     * Executes a {@code Callable} with {@code subject} as the
    +     * current subject.
    +     *
    +     * @implNote
    +     * By default, this method calls {@link #doAs(Subject, PrivilegedExceptionAction)
    +     * Subject.doAs(subject, altAction)} which stores the subject in
    +     * a new {@code AccessControlContext}, where {@code altAction.run()}
    +     * is equivalent to {@code action.call()} and the exception thrown is
    +     * modified to match the specification of this method. This preserves
    +     * compatibility with code that may still be calling
    +     * {@code getSubject(AccessControlContext)} which retrieves the subject
    +     * from an {@code AccessControlContext}. However,
    +     * if the system property {@code jdk.security.auth.subject.useTL}
    +     * is set to {@code true}, the current subject will be stored in an inheritable
    +     * {@code ThreadLocal} object. This behavior is subject to change in a
    +     * future version.
    +     *
    +     * @param subject the {@code Subject} that the specified {@code action}
    +     *               will run as.  This parameter may be {@code null}.
    +     * @param action the code to be run with {@code subject} as its current
    +     *               subject. Must not be {@code null}.
    +     * @param <T> the type of value returned by the {@code call} method
    +     *            of {@code action}
    +     * @return the value returned by the {@code call} method of {@code action}
    +     * @throws NullPointerException if {@code action} is {@code null}
    +     * @throws CompletionException if {@code action.call()} throws an exception.
    +     *      The cause of the {@code CompletionException} is set to the exception
    +     *      thrown by {@code action.call()}.
    +     * @see #current()
    +     * @since 18
    +     */
    +    public static <T> T callAs(final Subject subject,
    +            final Callable<T> action) throws CompletionException;
    
         /**
          * Perform work as a particular {@code Subject}.
          ....
    +     *
    +     * @deprecated This method depends on {@link AccessControlContext}
    +     *       which, in conjunction with
    +     *       {@linkplain SecurityManager the Security Manager}, is deprecated
    +     *       and subject to removal in a future release. However, performing
    +     *       work as a Subject is useful independent of the Security Manager.
    +     *       Thus, a replacement API named {@link #callAs} has been added
    +     *       which can be used to perform the same work.
          */
         @SuppressWarnings("removal")
    +    @Deprecated(since="18", forRemoval=true)
         public static <T> T doAs(final Subject subject,
                             final java.security.PrivilegedAction<T> action);
    
    
         /**
          * Perform work as a particular {@code Subject}.
          ....
    +     *
    +     * @deprecated This method depends on {@link AccessControlContext}
    +     *       which, in conjunction with
    +     *       {@linkplain SecurityManager the Security Manager}, is deprecated
    +     *       and subject to removal in a future release. However, performing
    +     *       work as a Subject is useful independent of the Security Manager.
    +     *       Thus, a replacement API named {@link #callAs} has been added
    +     *       which can be used to perform the same work.
          */
         @SuppressWarnings("removal")
    +    @Deprecated(since="18", forRemoval=true)
         public static <T> T doAs(final Subject subject,
                             final java.security.PrivilegedExceptionAction<T> action)
                             throws java.security.PrivilegedActionException;
     }






Comments
Moving to Approved.
04-11-2021

Moving to Provisional.
30-10-2021