Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-63575

JavaScriptMethod & 403 - No valid crumb was included in the request

    XMLWordPrintable

Details

    • Bug
    • Status: Open (View Workflow)
    • Blocker
    • Resolution: Unresolved
    • core
    • Jenkins: 2.254
      Plugins:
      <groupId>io.jenkins.plugins</groupId>
      <artifactId>jquery3-api</artifactId>
      <version>3.5.1-1</version>

    Description

      The following code results in a 403 - No valid crumb was included in the request when the page is loaded.

      public class MyLink implements RootAction {
          @JavaScriptMethod
          public void setUserId(final String value) {
              userId = value;
      }
      
      <st:bind var="instance" value="${it}"/>
      
      instance.setUserId($('#userId')
      

      org/kohsuke/stapler/bind.js has the following:

      if(window.jQuery === window.$) { //Is jQuery the active framework?
          $.ajax({
              type: "POST",
              url: url+methodName,
              data: stringify(a),
              contentType: 'application/x-stapler-method-invocation;charset=UTF-8',
              headers: {'Crumb':crumb},
              dataType: "json",
              success: function(data, textStatus, jqXHR) {
                  if (callback!=null) {
                      var t = {};
                      t.responseObject = function() {
                          return data;
                      };
                      callback(t);
                  }
              }
          });
          } else { //Assume prototype should work
          new Ajax.Request(url+methodName, {
              method: 'post',
              requestHeaders: {'Content-type':'application/x-stapler-method-invocation;charset=UTF-8','Crumb':crumb},
              postBody: stringify(a),
              onSuccess: function(t) {
                  if (callback!=null) {
                      t.responseObject = function() {
                          return eval('('+this.responseText+')');
                      };
                      callback(t);
                  }
              }
          });
      }
      

      And prototype.js has patch forAjax.Request to add `Jenkins-Crumb` to the request

      // KK patch -- handle crumb for POST automatically by adding a header
          if(this.options.method=="post") {
              if(this.options.requestHeaders==undefined)
                  this.options.requestHeaders = {};
              crumb.wrap(this.options.requestHeaders);
          }
      // KK patch until here
      

      Nothing for patching JQuery as far as I can tell.

      Seems a bit disjointed and would be better solved binding to the value returned from `SystemProperties.getString("hudson.security.csrf.requestfield", CrumbIssuer.DEFAULT_CRUMB_NAME)`

      Attachments

        Activity

          drulli Ulli Hafner added a comment -

          I can confirm that bug. It seems that actually something in the latest Jenkins versions changed that get Ajax calls blocked that worked before (latest LTS works fine). Ajax works on the job page (trend charts) but not on individual plugin views that use JS (and bootstrap). E.g. my warnings plugin tables will now be blocked with the same error message (no valid crumb in request).

          drulli Ulli Hafner added a comment - I can confirm that bug. It seems that actually something in the latest Jenkins versions changed that get Ajax calls blocked that worked before (latest LTS works fine). Ajax works on the job page (trend charts) but not on individual plugin views that use JS (and bootstrap). E.g. my warnings plugin tables will now be blocked with the same error message (no valid crumb in request).
          jglick Jesse Glick added a comment -

          Sounds straightforward to bisect Jenkins weekly versions, and then if necessary git bisect, to find the source of the regression.

          Write it up as a functional test.

          jglick Jesse Glick added a comment - Sounds straightforward to bisect Jenkins weekly versions, and then if necessary git bisect , to find the source of the regression. Write it up as a functional test.
          drulli Ulli Hafner added a comment - - edited

          Hmm, when I am running my UI test now everything looks fine. After reinstalling LTS everything looks fine as well. After reinstalling 2.255 everything works fine. That is strange...

          Could this somehow be related how long Jenkins is running? As far as I remember the crumbs have timeout?

          drulli Ulli Hafner added a comment - - edited Hmm, when I am running my UI test now everything looks fine. After reinstalling LTS everything looks fine as well. After reinstalling 2.255 everything works fine. That is strange... Could this somehow be related how long Jenkins is running? As far as I remember the crumbs have timeout?
          drulli Ulli Hafner added a comment -

          Ok, I now can reproduce it: the problem was that in one of my views I am loading jQuery before loading Prototype.js. After reverting that change it works again.

          So in summary: I don't think that the crumb resolutions works for jQuery in the moment (regardless of the Jenkins version).

          drulli Ulli Hafner added a comment - Ok, I now can reproduce it: the problem was that in one of my views I am loading jQuery before loading Prototype.js. After reverting that change it works again. So in summary: I don't think that the crumb resolutions works for jQuery in the moment (regardless of the Jenkins version).
          drulli Ulli Hafner added a comment - - edited

          prg0611 Can you please link to the source code of your Jelly view (or add a full code snippet)? In all of my views Prototype gets loaded first so this might be a simple workaround to use the right tag order.

          drulli Ulli Hafner added a comment - - edited prg0611 Can you please link to the source code of your Jelly view (or add a full code snippet)? In all of my views Prototype gets loaded first so this might be a simple workaround to use the right tag order.
          <?jelly escape-by-default='true'?>
          <j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler"
          	xmlns:l="/lib/layout" xmlns:bs="/bootstrap" xmlns:fa="/font-awesome">
          
          	<st:bind var="instance" value="${it}"/>
          
          	<st:header name="Content-Type" value="text/html;charset=UTF-8" />
          	<l:layout title="${it.displayName}" norefresh="true">
          
          		<st:include it="${it.owner}" page="sidepanel.jelly" />
          
          		<l:main-panel>
          			<st:adjunct includes="io.jenkins.plugins.jquery3" />
          			<st:adjunct includes="io.jenkins.plugins.bootstrap4" />
          			<st:adjunct includes="io.jenkins.plugins.data-tables" />
          
          			<div class="card">
          				<div class="card-body">
          					<div id="loader" class="ui dimmer">
          						<div class="ui text loader">Loading</div>
          					</div>
          
          					<form id="release_form">
          						<div id="error_message" class="ui negative message hidden">
          						    <fa:svg-icon name="times" class="close small"/>
          							<div id="error_message_content">
          							</div>
          						</div>
          					</form>
          				</div>
          			</div>
          		</l:main-panel>
          	</l:layout>
          </j:jelly>
          
          prg0611 Shaun Thompson added a comment - <?jelly escape-by- default = ' true ' ?> <j:jelly xmlns:j= "jelly:core" xmlns:st= "jelly:stapler" xmlns:l= "/lib/layout" xmlns:bs= "/bootstrap" xmlns:fa= "/font-awesome" > <st:bind var = "instance" value= "${it}" /> <st:header name= "Content-Type" value= "text/html;charset=UTF-8" /> <l:layout title= "${it.displayName}" norefresh= " true " > <st:include it= "${it.owner}" page= "sidepanel.jelly" /> <l:main-panel> <st:adjunct includes= "io.jenkins.plugins.jquery3" /> <st:adjunct includes= "io.jenkins.plugins.bootstrap4" /> <st:adjunct includes= "io.jenkins.plugins.data-tables" /> <div class= "card" > <div class= "card-body" > <div id= "loader" class= "ui dimmer" > <div class= "ui text loader" >Loading</div> </div> <form id= "release_form" > <div id= "error_message" class= "ui negative message hidden" > <fa:svg-icon name= "times" class= "close small" /> <div id= "error_message_content" > </div> </div> </form> </div> </div> </l:main-panel> </l:layout> </j:jelly>
          drulli Ulli Hafner added a comment -

          You need to move the bind tag inside of the layout tag. Typically I place it at the bottom before the JS code:
          https://github.com/jenkinsci/warnings-ng-plugin/blob/master/plugin/src/main/resources/io/jenkins/plugins/analysis/core/model/IssuesDetail/index.jelly

          drulli Ulli Hafner added a comment - You need to move the bind tag inside of the layout tag. Typically I place it at the bottom before the JS code: https://github.com/jenkinsci/warnings-ng-plugin/blob/master/plugin/src/main/resources/io/jenkins/plugins/analysis/core/model/IssuesDetail/index.jelly

          That was it as it looks like it was bound differently this time. I'll have to track it back to see where the difference lies.

          Was this referenced anywhere and I just missed it?

          Thanks

          prg0611 Shaun Thompson added a comment - That was it as it looks like it was bound differently this time. I'll have to track it back to see where the difference lies. Was this referenced anywhere and I just missed it? Thanks
          drulli Ulli Hafner added a comment -

          No, this is not referenced anywhere. I never noticed that it is even possible to use the jQuery path in Stapler bind. So this never worked before with Stapler in Jenkins. I'm not sure what would be a good place to document that behavior.

          drulli Ulli Hafner added a comment - No, this is not referenced anywhere. I never noticed that it is even possible to use the jQuery path in Stapler bind. So this never worked before with Stapler in Jenkins. I'm not sure what would be a good place to document that behavior.

          Ok good to know it wasn't just a matter of reading the doc. 1/2 the time I spend in creating a custom Jenkins plugin with any type of advanced behavior I feel like I'm treading into the unknown.

          prg0611 Shaun Thompson added a comment - Ok good to know it wasn't just a matter of reading the doc. 1/2 the time I spend in creating a custom Jenkins plugin with any type of advanced behavior I feel like I'm treading into the unknown.
          wfollonier Wadeck Follonier added a comment - Potential culprit: https://github.com/jenkinsci/jenkins/pull/4741/

          People

            Unassigned Unassigned
            prg0611 Shaun Thompson
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

              Created:
              Updated: